开发者

Background Worker in external reference (DLL) locking main thread

I use background worker almost daily and works great. Today I came to an instance though where I needed to put my background worker in a separate project then the one I was running because I needed to use this class in two different projects in my solution. When I tested the coding on a winforms form, it works perfectly, handling my coding on the background thread. When I try to reference this class from an external project, all of my coding seems to run just fine, but it does not appear to be doing anything on a background thread as it should be, causing my main window to lockup.

Is there any way around this / what is the best practice for ASYNC calls in an external class.

Note I basically created a class that u call start, and an event fires when data is ready, so it's not like my external project is waiting for the method to complete.

Thanks in advance


Example of my senerio

Solution ABC has two projects. Project A and Project B. Project A is my WPF application and B is my DLL doing the work. Inside project A I have

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 开发者_如何学PythonSub workerConnect_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles workerConnect.RunWorkerCompleted

  RaiseEvent Scanner_Connected()

End Sub

(Sorry I can't get it to show my coding as code, not plain text)


Use the debugger first. Set a breakpoint on the DoWork event handler. When it breaks, use Debug + Windows + Threads and verify that it runs on a worker thread and that you see the Main Thread listed. Double-click the main thread and look at the call stack, ensure it is idle and is not doing something like waiting for the BGW to complete. That's a guaranteed deadlock.

The next failure mode is one that's hard to diagnose. You can freeze the UI thread, even with a background worker, when you call ReportProgress too often. The UI thread is flooded with invoke requests and doesn't get around to doing its normal duties anymore. Like painting and responding to input. Everything still works like it should, the worker and the UI thread are actually running, you just can't see it.

This happens easily, reporting progress more than about a thousand times per second is the danger zone. It depends on how much work the UI thread needs to do in the ProgressChanged event handler. The best way to diagnose if that's your problem is to add System.Threading.Thread.Sleep(45) after the ReportProgress() call. This usually slows down the worker enough to give the UI thread a chance to catch up.

You solve it by reporting progress at a rate that's useful to human eyes. Which at 25 updates per second doesn't see anything but a blur anymore. Collect bgw results in a collection object like List<> so you can update the UI with a single call, something like AddRange(). This might still not be good enough if the BGW just generates results far faster than the UI can ever consume, you'll have to skip results or slow down the worker artificially.


The background worker handles it completed code in the main thread stoppping the UI from responding. Don't use the background worker if you wan't the UI to update while the backgroundworker is finishing.


If your external app is consoled based, use the ThreadPool instead to run your async work. The BackgroundWorker delegate needs a message pump in order to execute on the main thread.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜