如何在 Form 的 Closing 事件上停止 BackgroundWorker? [英] How to stop BackgroundWorker on Form's Closing event?

查看:23
本文介绍了如何在 Form 的 Closing 事件上停止 BackgroundWorker?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个生成 BackgroundWorker 的表单,它应该更新表单自己的文本框(在主线程上),因此 Invoke((Action) (...)); 调用.
如果在 HandleClosingEvent 我只做 bgWorker.CancelAsync() 然后我在 Invoke(...) 上得到 ObjectDisposedException打电话,可以理解.但是,如果我坐在 HandleClosingEvent 中等待 bgWorker 完成,那么 .Invoke(...) 永远不会返回,这也是可以理解的.

I have a form that spawns a BackgroundWorker, that should update form's own textbox (on main thread), hence Invoke((Action) (...)); call.
If in HandleClosingEvent I just do bgWorker.CancelAsync() then I get ObjectDisposedException on Invoke(...) call, understandably. But if I sit in HandleClosingEvent and wait for bgWorker to be done, than .Invoke(...) never returns, also understandably.

任何想法如何关闭此应用程序而不会出现异常或死锁?

Any ideas how do I close this app without getting the exception, or the deadlock?

以下是简单 Form1 类的 3 个相关方法:

Following are 3 relevant methods of the simple Form1 class:

    public Form1() {
        InitializeComponent();
        Closing += HandleClosingEvent;
        this.bgWorker.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
        while (!this.bgWorker.CancellationPending) {
            Invoke((Action) (() => { this.textBox1.Text = Environment.TickCount.ToString(); }));
        }
    }

    private void HandleClosingEvent(object sender, CancelEventArgs e) {
        this.bgWorker.CancelAsync();
        /////// while (this.bgWorker.CancellationPending) {} // deadlock
    }

推荐答案

据我所知,唯一的死锁安全和异常安全的方法是实际取消 FormClosing 事件.如果 BGW 仍在运行,则设置 e.Cancel = true 并设置一个标志以指示用户请求关闭.然后在 BGW 的 RunWorkerCompleted 事件处理程序中检查该标志,如果已设置,则调用 Close().

The only deadlock-safe and exception-safe way to do this that I know is to actually cancel the FormClosing event. Set e.Cancel = true if the BGW is still running and set a flag to indicate that the user requested a close. Then check that flag in the BGW's RunWorkerCompleted event handler and call Close() if it is set.

private bool closePending;

protected override void OnFormClosing(FormClosingEventArgs e) {
    if (backgroundWorker1.IsBusy) {
        closePending = true;
        backgroundWorker1.CancelAsync();
        e.Cancel = true;
        this.Enabled = false;   // or this.Hide()
        return;
    }
    base.OnFormClosing(e);
}

void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    if (closePending) this.Close();
    closePending = false;
    // etc...
}

这篇关于如何在 Form 的 Closing 事件上停止 BackgroundWorker?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆