I had the same problem with the concurrent web crawler described in the first edition of my book F# for Technical computing. For the second edition, I completely rewrote the code such that it can be invoked synchronously. I found it quite tricky to do elegantly so the book goes into some detail about both the abstract design and the concrete implementation of my solution. This allows the caller to post the message to start the asynchronous code and wait for it to complete and reply with its result before the caller continues which solves your problem and many others at the same time.

This is particularly useful in the context of FSI because it allows you to keep the results from an asynchronous worker for further dissection!

By on 7/16/2010 8:00 PM ()

Hello,

I have a few questions concerning this sample code:

1. Where it is Microsoft.FSharp.Control.Mailboxes ?

2. I can not use: req.GetResponseAsync() and reader.ReadToEndAsync(). They were renamed or moved I suppose.

There are many demos that are similar and I can not compile them because of the problems above.

Thanks,

-Anton

By on 4/15/2009 8:39 AM ()

Hello,

1. C:\Program Files\FSharp-1.9.6.2\lib\FSharp.Core\control.fs
2. req.GetResponseAsync() and reader.ReadToEndAsync() are extensions methods defined in FSharp.PowerPack.dll, you must add reference to FSharp.PowerPack.dll for using them.
You can find sources in C:\Program Files\FSharp-1.9.6.2\lib\FSharp.PowerPack\AsyncOperations.fs

By on 4/16/2009 6:47 AM ()
By on 6/2/2009 7:35 AM ()

Hi,

.PostSync(proc) doesn't seem to exist in F# 2.0.

Is there any other way to wait for the mailbox processing all it's messages.

Thanks, forki

By on 7/13/2010 6:24 AM ()

No APIs, but if you are the author of the mailbox or its processing loop, you can do a variety of things to signal this, depending on the logic of the app and processing loop. For example, the app can PostAndReply an 'AllDone' message, or the mailbox could publish the number of currently outstanding requests which could be polled... There is no one pattern that works for everything, it is just another small piece of synchronization code to design and implement in a way that's appropriate to whatever domain you're working in.

By on 7/13/2010 6:55 AM ()

Hi,

I 've just made a Google code project and added some samples that I made to work:
[link:code.google.com]
Everyone is welcome to contribute.

Cheers,
Anton

By on 4/16/2009 11:13 AM ()

Ideally you would want your processor to keep busy. You will run asynchronously when you want to have responsive user interface while you are performing some other calculations. The interpreter window in visual studio is a windows forms application, but for console applications there are no event loops to keep the thread busy. On the other hand, you might ask for an input to hold the thread as well like Console.ReadLine().

The sample uses post method of MailboxProcessor to asyncronusly post

the data. If you call it synchronously your thread will not die. Replace the last line of you code with the following code, or just add Console.Read() to the existing program.

1
2
let proc (c:#IChannel<string>) = "http://news.google.com"
urlCollector.PostSync(proc)
By on 2/21/2008 1:18 PM ()

Ideally you would want your processor to keep busy.

What about batch processing? When program must read input data from file, process these data, save result to output file and exit.

You will run asynchronously when you want to have responsive user interface while you are performing some other calculations.

As I understanding Async IO not only make more "live" UI, using async IO we add to heavy IO tasks more performance and scalability.

Replace the last line of you code with the following code, or just add Console.Read() to the existing program.

1
2
let proc (c:#IChannel<string>) = "http://news.google.com"
urlCollector.PostSync(proc)

After adding this line process sleep.

Any more idea?

By on 2/22/2008 4:54 AM ()

After adding this line process sleep.

Any more idea?

It doesn't look to me like MailboxProcessor supports a ``wait'' or ``join'' type method where you can block a thread and wait for the mailbox thread to finish.

The reason why this isn't a problem in FSI is because the process never exits. So, the background thread is never killed.

However, in .NET, background threads will be terminated when all foreground threads have exited. (That is part of what it means to be a background thread)

I think in the example that you have posted, the background thread will run forever. (It will block on

1
let! url = self.Receive()

, which is why you see the thread sleeping). So, you have to develop a strategy for it to exit.

The easiest way to kill the thread is to use a discriminated union to send a ``Die'' message when you no longer plan to get anything more out of the thread.

Something like:

1
2
3
4
5
6
7
// ...
urlCollector <-- "http://news.google.com"
urlCollector <-- "http://news.google.com"
urlCollector <-- "http://news.google.com"
urlCollector <-- "SENTINEL STRING: DIE!!!"
printfn "Press any key to continue."
System.Console.ReadKey() |> ignore

Or:

1
2
3
4
5
6
7
8
9
10
11
12
// ...
type Message<'a> =
    | Die // quit
    | Deliver of 'a // replace the current state

urlCollector <-- Deliver("http://news.google.com")
urlCollector <-- Deliver("http://news.google.com")
urlCollector <-- Deliver("http://news.google.com")
urlCollector <-- Die

printfn "Press any key to continue."
System.Console.ReadKey() |> ignore
By on 4/15/2009 9:37 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper