Task.Yield()之后SynchronizationContext丢失

时间:2015-07-19 23:45:33

标签: c# async-await synchronizationcontext

我一直在线程之间传递文化问题。我已经设法使用同步上下文使其有点工作,但在我的代码的一部分中,我使用Task.Yield()。在这段代码之后,我的上下文丢失意味着在此之后所有后续等待/收益不使用我的自定义SynchronizationContext。

我把它归结为一个非常简单的测试,我可以看到在Task.Yield之后,我们的SynchronizationContext丢失了。

同步上下文类:

public class TestSynchronizationContext : SynchronizationContext
{
}

单元测试:

[Test]
public async Task TestHere()
{
    TestSynchronizationContext context = new TestSynchronizationContext();
    SynchronizationContext.SetSynchronizationContext(context);
    var something1 = SynchronizationContext.Current;
    await Task.Yield();
    var something = SynchronizationContext.Current;
}

编辑:如果我使用新的任务,如果我可以传入正确的TaskScheduler,则保留上下文(虽然......这是调度程序,而不是同步上下文)。如下:

[Test]
public async Task TestHere()
{
    TestSynchronizationContext context = new TestSynchronizationContext();
    SynchronizationContext.SetSynchronizationContext(context);
    CultureInfo taskCulture = null;
        Task.Factory.StartNew(
            () => { taskContext = SynchronizationContext.Current; },
            CancellationToken.None,
            TaskCreationOptions.None,
            TaskScheduler.FromCurrentSynchronizationContext()
            ).Wait();
    Assert.AreEqual(context.GetType(), taskContext.GetType());
}

1 个答案:

答案 0 :(得分:3)

您的SychronizationContext必须将自己设为Current。如果您的SynchronizationContext用于专用线程,则只需在主循环中设置一次当前线程;如果它使用线程池线程来执行(如在你的示例代码中),你应该在每次借用其中一个线程时设置它(并在将线程返回到线程池之前清除它)。