Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
468 views
in Technique[技术] by (71.8m points)

c# - Why BackgroundWorker always is busy?

I realized something strange in my background worker in my WPF application.

What I'm trying to accomplish right now is to wait until the BW finishes to start another thread.

Check the following code:

if (bw.IsBusy)
{
    bw.CancelAsync();

    System.Threading.ThreadStart WaitThread = 
        new System.Threading.ThreadStart(delegate() {
            while (bw.IsBusy)
            {
                System.Threading.Thread.Sleep(100);
            }

            bw.RunWorkerAsync();
        });

    System.Windows.Application.Current.Dispatcher.Invoke(
        System.Windows.Threading.DispatcherPriority.Normal,
        WaitThread);  // if I remove this line, bw fires RunWorkerAsyncEvent
}
else
{
    bw.RunWorkerAsync();
}

Please note that I added a Dispatcher.Invoke to wait until the bw is not busy, but ALL THE TIME IS BUSY if I Invoke it and never fires the RunWorkerAsyncCompleted event. Although,, if I remove that line, FIRES the event and it's really strange that.

How can I wait until the bw finishes?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is called "deadlock", a very common threading problem. The BGW cannot stop being busy until the RunWorkerCompleted event runs. That event runs on your app's main thread, it can only run when your main thread isn't busy doing something else. It has to be idle, running inside the dispatcher loop.

But your main thread isn't idle, it is stuck inside the while() loop waiting for IsBusy to return false. So the event can never run since the main thread is busy waiting for the BGW to complete, the BGW cannot complete because the main thread never goes idle. "Deadly embrace", aka deadlock.

You will have to do this differently, you cannot wait. Say by creating another instance of BGW. Or moving the code after the wait into the RunWorkerCompleted event handler. If it is activated by, say, a button's Click event then be sure to disable the button when call RunWorkerAsync(), re-enable it in RunWorkerCompleted.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...