0

我正在运行一个很长的任务,BackgroundWorker通过ReportProgress. 但是,在这个过程的中间,我需要进行 COM 调用以获取一些数据,并且我认为我需要在 UI 线程上进行。我尝试通过 Control.Invoke 执行此操作。但是,我遇到了僵局。不能Control.InvokeBackgroundWorker(with ShowDialog) 中使用吗?

我试图简化代码:

        var log = new LogWindowForm();
        worker.DoWork += (sender, args) =>
        {
                creator.LogProgress = (s, i) => worker.ReportProgress(i,s);
                creator.GetMoreDataFunc = (s) => InvokeGetMoreDataOnGuiThread(log, s);
                ...
                var data = GetMoreDataFunc("id:"+id)
        };
        worker.RunWorkerAsync();
        log.ShowDialog();


    private Dictionary<string, string> InvokeGetMoreDataOnGuiThread(Control invokeControl, string id)
    {
        var data = new Dictionary<string, string>();
        Action action = () => data = GetMoreDataFromComObject(mainComObject, id);
        invokeControl.Invoke(action); // deadlock!
        return data;
    }

编辑:

没有例外,用户界面不断更新,但它停止了进步。Break All 显示 Control.Invoke 调用中的工作线程和 ShowDialog 调用中某处的 GUI 线程。

GUI 线程似乎在消息循环中:

System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x65 bytes

我想这就是 UI 不断更新的原因。BackgroundWorker 内部是否有一些锁定?

4

1 回答 1

0

一个猜测,因为我不知道 COM 对象做什么或需要什么:

COM 对象需要 UI htread 的原因可能是因为(在大多数情况下)UI 线程被标记为 STA 线程。

如果 COM 对象需要单线程 Appartment,您可以使用标记为 STA 线程的非 UI 线程。这样你就不再需要 UI 线程了。

请参阅:您能解释一下 STA 和 MTA 吗?

和:.NET 中 STA 的解释

以及如何制作 .NET 线程 STA 或 MTA使用属性

于 2013-01-23T10:28:48.220 回答