【发布时间】:2015-01-27 06:45:50
【问题描述】:
我遇到了一个单元测试失败的问题,因为 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(),测试就应该通过。
【问题讨论】:
-
是否出现异常?
-
@SriramSakthivel 愚蠢的问题 - 您是否尝试过
var f = new Form();未评论?我是一个 MsTest,VS2013u4,Win8.1,Net 4.5.1 -
@OffHeGoes 抱歉,我忽略了这一点。现在写一个答案:)
-
@YuvalItzchakov 不,也不例外。如果我删除
TaskScheduler.FromCurrentSynchronizationContext(),它也会通过。
标签: c# winforms unit-testing task-parallel-library