The reponse callback to a asynchronous SendOut() operation should be routed to the same thread as the send was called from.
Otherwise send and receive operations of an actor do not run on the same thread.
Accessing your data from different threads leads to race conditions - very difficult to find programming errors.
The recommended cure are locks, but they may lead to deadlocks - even more difficult to find programming errors!
We want lockfree code and therefore accept only a single thread for an actor.
This is possible as long as the SendOut() was made from a Microsoft.Windows.Forms- or a WPF class. These objects are created from a thread that has a "System.Threading.SynchronizationContext". SynchronizationContext is the base class for the implementation of a message queue. Notably it contains the asynchronous Post() method.
There is a very fine implementation of "System.Threading.SynchronizationContext" in Nito.Async.ActionThread (http://nitoasync.codeplex.com).
It perfectly fits AsyncWcfLib and is used e.g. in Test1.Client. ActionThread has a message queue and a dispatcher. The library also contains a matching timer class.
You might think that async-await is another solution for lockfree code.
This is only true in the presence of a "System.Threading.SynchronizationContext" (like in Nito.Async.ActionThread, WinForms or WPF).
Otherwise your continuation code after await runs on a threadpool-thread and you are accessing the state of your actor from two threads (maybe from two CPU's) possibly at the same time.
The .NET framework defaults to the so called "free-threaded" context (System.Threading.SynchronizationContext.Current == null). It just uses another threadpool thread after an await or for a response callback event.
Free-threading is used in:
There is more information in
Wiki: Async-Await and Actor rules!
Wiki: Asynchronous Responses
Wiki: Home
Wiki: Implement a client using AsyncWcfLib
Wiki: Run AsyncWcfLib.Test1