我正在面对一个单元测试使用任务延续和DispatcherSynchrinizationContext的代码时我不明白的问题。
我的单元测试代码:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext());
var class1 = new Class1();
var result = class1.MyAsyncMethod().Result;
Assert.IsTrue(result == "OK");
}
}
正在测试的代码:
class Class1
{
public Task<string> MyAsyncMethod()
{
var tcs = new TaskCompletionSource<string>();
MyInnerAsyncMethod()
.ContinueWith(t =>
{
// Never reached if TaskScheduler.FromCurrentSynchronizationContext() is set
tcs.SetResult("OK");
}, TaskScheduler.FromCurrentSynchronizationContext());
return tcs.Task;
}
private Task<string> MyInnerAsyncMethod()
{
var tcs = new TaskCompletionSource<string>();
tcs.SetResult("OK");
return tcs.Task;
}
}
问题是“ContinueWith”方法中包含的代码永远不会到达 IF 我指定“TaskScheduler.FromCurrentSynchronizationContext()”。如果我删除此参数,则继续正确执行...
任何想法或建议?
答案 0 :(得分:2)
我认为这是因为虽然你已经创建了一个新的DispatcherSynchronisationContext,但是没有实际的线程运行一个调度循环来执行你的任务。
尝试将其放在测试开始时:
// Create a thread
Thread newWindowThread = new Thread(new ThreadStart( () =>
{
// Create our context, and install it:
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
// Start the Dispatcher Processing
System.Windows.Threading.Dispatcher.Run();
}));
礼貌: http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/
答案 1 :(得分:2)
lain 你让我走的正确,谢谢!!
我没有修改我正在测试的代码,这是测试代码的新实现,按预期工作:
[TestClass]
public class UnitTest1
{
private ExecutionContext _executionContext;
[TestInitialize]
public void OnSetup()
{
_executionContext = CreateExecutionContext();
SynchronizationContext.SetSynchronizationContext(_executionContext.DispatcherSynchronizationContext);
}
[TestCleanup]
public void OnTearDown()
{
// stops the dispatcher loop
_executionContext.Dispatcher.InvokeShutdown();
}
[TestMethod]
public void TestMethod1()
{
var class1 = new Class1();
var result = class1.MyAsyncMethod().Result;
Assert.IsTrue(result == "OK");
}
/* Helper classes and methods */
private ExecutionContext CreateExecutionContext()
{
var tcs = new TaskCompletionSource<ExecutionContext>();
var mockUIThread = new Thread(() =>
{
// Create the context, and install it:
var dispatcher = Dispatcher.CurrentDispatcher;
var syncContext = new DispatcherSynchronizationContext(dispatcher);
SynchronizationContext.SetSynchronizationContext(syncContext);
tcs.SetResult(new ExecutionContext
{
DispatcherSynchronizationContext = syncContext,
Dispatcher = dispatcher
});
// Start the Dispatcher Processing
Dispatcher.Run();
});
mockUIThread.SetApartmentState(ApartmentState.STA);
mockUIThread.Start();
return tcs.Task.Result;
}
internal class ExecutionContext
{
public DispatcherSynchronizationContext DispatcherSynchronizationContext { get; set; }
public Dispatcher Dispatcher { get; set; }
}
/* ------ */
}