【问题标题】:Cancelling a BackgroundWorker that performs a DB call取消执行数据库调用的 BackgroundWorker
【发布时间】:2012-08-02 08:58:59
【问题描述】:

我有一个带有子窗口的 WPF 应用程序。在其中,我正在对按钮单击(在后台工作人员中)进行数据库连接检查。该过程需要一些时间才能完成,在这段时间内,如果用户通过单击关闭按钮关闭子窗口,窗口会关闭,但后台工作人员会继续运行并在一段时间后显示消息。

这里是示例代码:

BackgroundWorker worker;
private void Button_Click(object sender, RoutedEventArgs e)
            {
                worker = new BackgroundWorker();
                worker.WorkerSupportsCancellation = true;
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                worker.DoWork += new DoWorkEventHandler(worker_DoWork);

                bsyInd.IsBusy = true;
                worker.RunWorkerAsync();
            }
     void worker_DoWork(object sender, DoWorkEventArgs e)
            {
                try
                {
                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }

                    // checking database connectivity
                    string connstring=myconnstring;
                    SqlConnection con=new SqlConnection(connstring);
                    con.Open();
                    if(con.State==ConnectionState.Open)
                       e.Result=true;
                }
                catch (Exception)
                {
                 e.Result=false;
                }

            }

            void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                bool canConnect=(bool)e.Result;
                if(canConnect)
                    MessageBox.Show("Connected");
                else
                    MessageBox.Show("Failed");

                bsyInd.IsBusy = false;
            }

    //close child window
    private void ChildWindow_CloseButton_Click(object sender, RoutedEventArgs e)
    {
        //cancel the running process
        worker.CancelAsync();
    }

我在网上找到的所有解决方案都显示了在 Do_Work 内的循环中持续监视/轮询后台工作程序的 CancellationPending 属性的示例。由于我打算做的过​​程不需要任何循环,我如何监控子窗口关闭按钮单击事件的 CancellationPending 状态并取消后台进程?

提前致谢。

【问题讨论】:

  • 有没有办法中止阻塞SqlConnection.Open请求?

标签: c# .net wpf multithreading backgroundworker


【解决方案1】:

如果有中止对SqlConnection.Open 的阻塞调用的方法,您可以简单地将SqlConnection 对象声明为您的类中的成员变量,并在关闭按钮处理程序中执行中止调用。

private SqlConnection con;

private void ChildWindow_CloseButton_Click(object sender, RoutedEventArgs e) 
{ 
    if (con != null)
    {
        con.Dispose(); // or whatever would abort Open()
        con = null;
    }
}  

在工作线程中 Open 可能会抛出某种 Aborted 异常,您可以捕获并设置 e.Cancel = true;

【讨论】:

  • 感谢您的提示。实际上,当后台工作人员检查数据库连接时,我有一个繁忙的指示器。我是否可以选择保持该功能不变,同时还能取消/中止窗口关闭时的阻塞调用。
  • 您还应该能够更新/删除假设异常的 catch 块中的忙指示符。
  • Clemens - 我试过了,但异常需要一段时间才能发生。对 dispose() 的调用不会立即中止连接。
  • 我没有看到任何其他干净的方式。如果真的需要太长时间,您将不得不设置自己的连接线程并按照文森特的建议中止它。但你必须知道你在做什么。
【解决方案2】:

Dennis,您可以使用 AutoResetEvent 的方法,请参阅 AutoResetEvent Class

您向发生 sql 连接的线程发出信号,表明可以释放资源。

您仍在使用单独的线程,因此不应阻塞任何内容,但现在可以在线程之间进行通信并特别通知其中一个线程释放资源。如果这不是预期的格式,请致歉。

该链接有一个如何使用 AutoResetEvent 的示例。

【讨论】:

    猜你喜欢
    • 2018-03-18
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多