Task.Yield() 后 SynchronizationContext 丢失
SynchronizationContext lost after Task.Yield()
我在线程之间传递文化时遇到了问题。我已经设法使用同步上下文让它有点工作,但在我的代码的一部分中我使用了 Task.Yield()。在这段代码之后,我的上下文丢失了,这意味着在这一点之后所有后续 awaits/yields 都不要使用我的自定义 SynchronizationContext。
我已将其归结为一个非常简单的测试,我可以看到在 Task.Yield 之后,我们的 SynchronizationContext 丢失了。
同步上下文 Class:
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());
}
您的 SychronizationContext
必须将自己设置为 Current
。如果您的 SynchronizationContext
用于专用线程,则只需在主循环中设置一次 current 即可;如果它使用线程池线程来执行(如在您的示例代码中),您应该在借用其中一个线程时设置它(当然,在将线程返回到线程池之前清除它)。
我在线程之间传递文化时遇到了问题。我已经设法使用同步上下文让它有点工作,但在我的代码的一部分中我使用了 Task.Yield()。在这段代码之后,我的上下文丢失了,这意味着在这一点之后所有后续 awaits/yields 都不要使用我的自定义 SynchronizationContext。
我已将其归结为一个非常简单的测试,我可以看到在 Task.Yield 之后,我们的 SynchronizationContext 丢失了。
同步上下文 Class:
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());
}
您的 SychronizationContext
必须将自己设置为 Current
。如果您的 SynchronizationContext
用于专用线程,则只需在主循环中设置一次 current 即可;如果它使用线程池线程来执行(如在您的示例代码中),您应该在借用其中一个线程时设置它(当然,在将线程返回到线程池之前清除它)。