为什么SynchronizationContext无法正常工作?

Ale*_*man 3 .net multithreading asynchronous synchronizationcontext

我有以下代码:

[TestMethod]
public void StartWorkInFirstThread()
{
    if (SynchronizationContext.Current == null)
        SynchronizationContext.SetSynchronizationContext(
            new SynchronizationContext());

    var syncContext = SynchronizationContext.Current;

    Console.WriteLine("Start work in the first thread ({0})", 
        Thread.CurrentThread.ManagedThreadId);

    var action = ((Action) DoSomethingInSecondThread);
    action.BeginInvoke(CallbackInSecondThread, syncContext);

    // Continue its own work
}

private static void DoSomethingInSecondThread()
{
    Console.WriteLine("Do something in the second thread ({0})", 
        Thread.CurrentThread.ManagedThreadId);   
}

private void CallbackInSecondThread(IAsyncResult ar)
{
    Console.WriteLine("Callback in the second thread ({0})", 
        Thread.CurrentThread.ManagedThreadId);
    var syncContext = (SynchronizationContext) ar.AsyncState;
    syncContext.Post(CallbackInFirstThread, null);
}

private void CallbackInFirstThread(object obj)
{
    Console.WriteLine("Callback in the first thread ({0})",
        Thread.CurrentThread.ManagedThreadId);
}
Run Code Online (Sandbox Code Playgroud)

我希望最后一个方法在第一个线程中执行,即从中获取SynchronizationContext的初始线程,因为我调用Post()了这个上下文的方法.就是这样的:

Start work in the first thread (28)
Do something in the second thread (17)
Callback in the second thread (17)
Callback in the first thread (28)
Run Code Online (Sandbox Code Playgroud)

是不是SynchronizationContext的含义?但实际上我有以下输出:

Start work in the first thread (28)
Do something in the second thread (17)
Callback in the second thread (17)
Callback in the first thread (7)
Run Code Online (Sandbox Code Playgroud)

问题是什么?SynchronizationContext出了什么问题,或者我有一些误解?

更新:我使用Resharper测试运行器将此方法称为单元测试.

Ale*_*nin 8

请参见http://www.codeproject.com/KB/threads/SynchronizationContext.aspx

有你需要的答案.您必须覆盖SynchronizationContext以使其正确处理您的操作.

阅读从:

请注意,DoWork在线程11上执行,与Run1相同.进入主线程的SynchronizationContext并不多.为什么?这是怎么回事?嗯......当你意识到生活中没有任何东西是免费的时候,这就是你的一部分.线程不能只是在它们之间切换上下文,它们必须有一个内置的基础结构才能这样做.例如,UI线程使用消息泵,在其SynchronizationContext中,它利用消息泵同步到UI线程.

  • Send只是在调用线程上调用委托(没有任何类型的线程切换),Post也做同样的事情,但只是使用ThreadPool以异步方式执行.在我看来,这个课应该是抽象的.这个类的默认实现是混乱和无用的. (5认同)
  • @Rory,可能有一个NoSynchronizationContext类. (2认同)

des*_*sco 5

SynchronizationContext的默认实现只是在调用线程中执行传递的委托(在调用Send/Post方法的线程中,而不是捕获上下文的线程).如果您需要某些特定行为,例如某些操作的线程关联,则应手动实现.BCL包含一些简化UI互操作性的现成实现,如WindowsFormsSynchronizationContextDispatcherSynchronizationContext.