我遇到了一个单元测试问题,因为TPL任务从未执行其ContinueWith(x, TaskScheduler.FromCurrentSynchronizationContext())
而失败。
问题的原因是在任务启动之前意外创建了Winforms UI控件。
以下是可重现该问题的示例。如果按原样运行测试,则测试通过。如果取消注释Form行并运行测试,则测试失败。
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
// Create new sync context for unit test
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
var waitHandle = new ManualResetEvent(false);
var doer = new DoSomethinger();
//Uncommenting this line causes the ContinueWith part of the Task
//below never to execute.
//var f = new Form();
doer.DoSomethingAsync(() => waitHandle.Set());
Assert.IsTrue(waitHandle.WaitOne(10000), "Wait timeout exceeded.");
}
}
public class DoSomethinger
{
public void DoSomethingAsync(Action onCompleted)
{
var task = Task.Factory.StartNew(() => Thread.Sleep(1000));
task.ContinueWith(t =>
{
if (onCompleted != null)
onCompleted();
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
有人能解释为什么会这样吗?
我原以为是因为使用了错误的SynchronizationContext
,但实际上,ContinueWith
根本没有执行!而且,在这个单元测试中,是否使用了正确的SynchronizationContext
都无关紧要,因为只要在任何线程上调用了waitHandle.set()
,测试就应该通过。
var f = new Form();
的注释去掉了吗?我在 MsTest、VS2013u4、Win8.1、Net 4.5.1 上测试过。 - oatsodaTaskScheduler.FromCurrentSynchronizationContext()
,它也会通过。 - oatsoda