gpt4 book ai didi

c# - 为什么 BackgroundWorker 在此单元测试中没有在正确的线程上调用 RunWorkerCompleted?

转载 作者:太空狗 更新时间:2023-10-29 22:23:17 28 4
gpt4 key购买 nike

backgroundWorker 的全部意义在于在完成耗时任务后更新 UI。该组件在我的 WPF 应用程序中像宣传的那样工作

但是在我的测试中,回调不会在调用线程上调用。

[Test]
public void TestCallbackIsInvokedOnClientThread()
{

var clientId = Thread.CurrentThread.ManagedThreadId;
int callbackThreadId = -1;
var manualEvent = new ManualResetEventSlim(false);

var someUIControl = new TextBox();
var bw = new BackgroundWorker();

bw.DoWork += (s,e) => e.Result = 5 ; // worker thread

bw.RunWorkerCompleted += (s, e) =>
{
try
{
callbackThreadId = Thread.CurrentThread.ManagedThreadId;
//someUIControl.Text = callbackThreadId.ToString();
manualEvent.Set();
}
catch (System.Exception ex)
{
Console.Out.WriteLine(ex.ToString());
}
};
bw.RunWorkerAsync();

if (!manualEvent.Wait(5000))
Assert.Fail("no callback");
Assert.AreEqual(clientId, callbackThreadId);
}

结果消息:Assert.AreEqual 失败。预期:<15>。实际:<10>。未在客户端线程上调用回调

我错过了什么?

在单元测试中我看到类似的行为

------ Run test started ------
MainThread Id =21
Worker Thread Id =9
Callback Thread Id =9

在 Wpf 应用程序中,这将是

MainThread Id =1
Worker Thread Id =14
Callback Thread Id =1

更新:根据 Justin 的回答,进行了以下更改,现在测试通过了

  • 在创建 BackgroundWorker 之前SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(control.Dispatcher));
  • 不要使用事件在线程之间发送信号,而是模拟消息泵

.

for (int i = 0; i < 3; i++)
{
control.Dispatcher.Invoke(DispatcherPriority.Background,
new Action(delegate { }));
Thread.Sleep(50);
}

最佳答案

由于您在不同的环境下运行,行为会有所不同。

当您调用 bw.RunWorkerAsync() 时,会捕获 SynchronizationContext。这用于发出 RunWorkerCompleted 调用。

在 WPF 下,它将使用 DispatcherSynchronizationContext,它将完成的回调编码回 UI 线程。在测试中,这种编码是不必要的,因此它保留在后台工作线程中。

关于c# - 为什么 BackgroundWorker 在此单元测试中没有在正确的线程上调用 RunWorkerCompleted?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13527442/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com