SynchronizationContext question

C

Coder

I was expecting my DoWork method to be executed on the Run1 thread,
instead it is executed on the main thread. Why?

class Program
{
private static SynchronizationContext mT1 = null; // setting
it in Run1 thread

static void Main(string[] args)
{
int id = Thread.CurrentThread.ManagedThreadId;
Trace.WriteLine(id);
Thread t1 = new Thread(new ThreadStart(Run1));
t1.Start();
Thread.Sleep(10);
var context = mT1;
context.Send(DoWork, null);

}

static private void Run1()
{
mT1 = SynchronizationContext.Current;
int id = Thread.CurrentThread.ManagedThreadId;
Trace.WriteLine(id);

while (true)
Thread.Sleep(10000000);

}

static void DoWork(object state)
{
int id = Thread.CurrentThread.ManagedThreadId;
Trace.WriteLine(id);

}
}
 
A

Anthony Jones

Peter Duniho said:
Check the docs. Your "t1" thread has no way to receive synchronized
invocations, and so .NET does the best it can, which is to execute the
method on the calling thread instead.

Where is this behaviour documented, it seems a strange choice for .NET to
make? Can .NET determine that it is safe to execute DoWork on a different
thread than was intended? I guess for this simple code it well do but in
general I can't see how it could.
 
A

Anthony Jones

Peter Duniho said:
It doesn't seem so to me. Even for unmanaged code, Windows can go only so
far in hijacking a thread to execute asynchronous calls. For .NET code,
you really want a well-defined mechanism to dispatch a delegate on an
arbitrary thread. You can't go around just interrupting executing threads
to execute the delegate, so you need for the thread to have some sort of
well-defined way for it to receive the delegate and execute it in an
orderly way.

For Windows Forms applications, this is the message pump loop, and for WPF
this is the dispatcher's message pump (which is essentially the same thing
that Windows Forms has, but with a slightly different description).

You'll note that there are actually only two defined
SynchronizationContext subclasses defined, one for Forms and one for WPF.
If you try to get a SynchronizationContext from a thread that has neither
a Forms or WPF message loop, there's no well-defined way for
SynchronizationContext to map back to the thread, and so you get a basic
"no-op" instance instead.


Define "intended". :) As far as safety goes, the SynchronizationContext
is not itself documented as providing this kind of thread affinity. From
MSDN (on the above-mentioned URL): "The SynchronizationContext class is a
base class that provides a free-threaded context with no
synchronization." In other words, unless you get a subclass that _does_
provide synchronization, you don't actually get any synchronization from
SynchronizationContext.

Sure, that means that the name of the class is possibly a bit confusing.
:) But this isn't the only example of a class that provides some base
functionality by default, but which has to be subclassed in order to get
the true value from it. .NET doesn't even have exclusive rights to such
examples.

So, back to my original comment...in this case, what's the "intent"? If
you get SynchronizationContext.Current on a thread that isn't a Forms or
WPF message thread, then given the documentation it could be argued that
you "intend" to get a free-threaded version of SynchronizationContext, and
thus it _is_ intended for the delegate to be executed on the same thread
on which the Send() method is called.

It's true that there's a bit of a gotcha here for the unwary programmer
that doesn't read the documentation. But, that really just means that the
unwary programmer should have read the documentation. There are lots of
ways to get unintended behavior if one doesn't follow the documentation
closely. :)

Thanks I grasp it now, I've only seen it used as
WindowsFormsSychronizationContext and I didn't scuritinize the OP code
fully.

I think the intent of the code its clear, so is the name of the class being
used, as you say the actualy behaviour described in the documentation
doesn't match the expectation that the class name raises.

I'm wondering why MS didn't make that class an abstract.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top