后台外部引用(DLL)锁定主线程的工作者

时间:2011-03-21 12:38:40

标签: c# vb.net multithreading backgroundworker

我几乎每天都使用后台工作人员而且效果很好。今天我来到了一个实例,虽然我需要将我的后台工作者放在一个单独的项目中,然后是我正在运行的项目,因为我需要在我的解决方案中将这个类用于两个不同的项目中。当我在winforms表单上测试编码时,它完美地运行,在后台线程上处理我的编码。当我尝试从外部项目引用这个类时,我的所有编码似乎运行得很好,但它似乎没有在后台线程上做任何事情,因为它应该是,导致我的主窗口锁定。

有没有办法解决这个问题/什么是外部类ASYNC调用的最佳做法。

注意我基本上创建了一个调用start的类,并且在数据就绪时会触发事件,因此我的外部项目不会等待方法完成。

提前致谢


我的senerio示例

解决方案ABC有两个项目。项目A和项目B.项目A是我的WPF应用程序,B是我的DLL工作。在项目A里面我有

Dim SmartCardData as new Solution.B()
SmartCardData.Start()

Project B has a sub

Public Sub Start()

   worker.workerConnect.RunWorkerAsync()

End Sub

Private Sub workerConnect_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles workerConnect.DoWork

'loop 10 seconds connecting to my device
e.Result = true

End Sub

Private Sub workerConnect_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles workerConnect.RunWorkerCompleted

  RaiseEvent Scanner_Connected()

End Sub

(抱歉,我无法将其编码显示为代码,而不是纯文本)

3 个答案:

答案 0 :(得分:1)

首先使用调试器。在DoWork事件处理程序上设置断点。当它中断时,使用Debug + Windows + Threads并验证它是否在工作线程上运行,并且您看到列出了主线程。双击主线程并查看调用堆栈,确保它处于空闲状态,并且没有像等待BGW完成那样做。这是一个有保障的僵局。

下一种失败模式很难诊断。当您经常调用ReportProgress时,即使使用后台工作程序,也可以冻结UI线程。 UI线程充满了调用请求,并且不再需要执行正常的任务。喜欢绘画和回应输入。一切仍然像它应该工作,工作者和UI线程实际上正在运行,你只是看不到它。

这很容易发生,每秒报告进度超过一千次是危险区域。这取决于UI线程在ProgressChanged事件处理程序中需要做多少工作。诊断问题的最佳方法是在ReportProgress()调用之后添加System.Threading.Thread.Sleep(45)。这通常会减慢工作人员的速度,使UI线程有机会赶上。

您可以通过以对人眼有用的速度报告进度来解决问题。每秒25次更新除了模糊之外什么都看不到。将bgw结果收集到像List<>这样的集合对象中所以你可以通过一次调用来更新UI,比如AddRange()。如果BGW生成的结果远远超过用户界面消耗的结果,那么这可能仍然不够好,你必须跳过结果或人为地减慢工作人员。

答案 1 :(得分:0)

后台工作者在主线程中处理它完成的代码,阻止UI响应。如果您在后台工作完成时不想更新UI,请不要使用后台工作程序。

答案 2 :(得分:0)

如果您的外部应用程序是基于安慰的,请使用ThreadPool来运行异步工作。 BackgroundWorker委托需要一个消息泵才能在主线程上执行。