【问题标题】:Closing the form when backgroundWorker stops workingbackgroundWorker 停止工作时关闭表单
【发布时间】:2013-05-27 09:38:50
【问题描述】:

我正在开发一个应该从 Mifare 智能卡读取数据的应用程序。我必须创建一个表单,它会定期检查 Mifare 阅读器,当卡在范围内时,读取其序列号并将其发送到父表单。我设法让后台工作人员读取序列号,但由于它会导致跨线程调用错误,我无法从中关闭表单。有没有办法监控 backGroundWorker 所做的工作,当它成功读取卡 ID 时,停止它并关闭子窗体? 这是我在 DoWork 方法中使用的代码:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    while (!worker.CancellationPending)
    {
        MifareReader.CommPort = 4;
        MifareReader.PortOpen = true;
        MifareReader.mfAutoMode(true);               
        MifareReader.mfRequest();                
        if (CardID == "0" || CardID == string.Empty)
        {
            MifareReader.mfRequest();
            CardID = MifareReader.mfAnticollision().ToString();
            MifareReader.mfHalt();
        }
        else if (CardID != "0" && CardID != string.Empty)
        {
            MessageBox.Show(ObrnutiID);
            worker.CancelAsync();                    
        }
        MifareCitac.mfHalt();
    }
}

这段代码完成了它的工作,但我必须手动关闭表单。有没有办法检查 CardID 变量是否在主线程中更改了它的值,如果是,请关闭表单。 我试图通过使用计时器来解决这个问题,但是当我这样做时,计时器会阻塞主窗体线程,并且我无法手动关闭它(当然我必须能够)。你能提出解决这个问题的方法吗?

【问题讨论】:

  • 在 DoWork 事件处理程序中调用 CancelAsync() 没有什么意义。只需使用 break 即可跳出 while() 循环。在 RunworkerCompleted 事件处理程序中关闭窗口很简单。更难解决的问题是当用户在工作人员完成之前关闭窗口时要做什么。不要忽视这一点。检查this answer

标签: c# multithreading backgroundworker


【解决方案1】:

您可以使用BackgroundWorker.RunWorkerCompleted 事件来监控BackgroundWorker 何时完成。

在后台操作完成、取消或引发异常时发生。

从那里,您可以以编程方式关闭表单。

【讨论】:

  • 好的,但是我如何向BackgroundWorker“解释”他已经完成(这是我第一次使用BackgroundWorker,所以请耐心等待)。从逻辑上讲,当 CardID 从“0”或 string.Empty 变为某个数字时,他的任务就完成了。发生这种情况时,我如何告诉 BackgroundWorker 他应该完成它的工作?
  • 这是您在DoWork 方法中定义的。您在 OP 中使用的 while 语句定义了循环退出和方法返回的点。现在,您正在等待取消该过程。当 DoWork 方法结束时,BackgroundWorker 认为其工作已完成,并将触发 RunWorkerCompleted 事件。
【解决方案2】:

您可以编写 BackgroundWorker,使其在完成工作后返回。

然后在您的主表单中,订阅BackgroundWorker.RunWorkerCompleted 并做出适当的回应,大概只需关闭表单即可。

【讨论】:

    【解决方案3】:

    从你的 backgroundWorker 添加 RunWorkerCompleted 事件:

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        this.Close() // Closes the form.
    }
    

    【讨论】:

      【解决方案4】:

      您可以通过检查 InvokedRequired 并尝试使用委托来 BeginInvoke 来避免跨线程调用错误。

      【讨论】:

        【解决方案5】:

        正如其他人提到的,这里是如何实现BackgroundWorker.RunWorkerCompleted 事件:

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            bool found = false;
                    var worker = sender as BackgroundWorker;
            while (!worker.CancellationPending && !found)
            {
                MifareReader.CommPort = 4;
                MifareReader.PortOpen = true;
                MifareReader.mfAutoMode(true);               
                MifareReader.mfRequest();                
                if (CardID == "0" || CardID == string.Empty)
                {
                    MifareReader.mfRequest();
                    CardID = MifareReader.mfAnticollision().ToString();
                    MifareReader.mfHalt();
                }
                else
                {
                    e.Result = ObrnutiID;
                    found = true;
                    MifareCitac.mfHalt();
                }
            }
            if (worker.CancellationPending)
            {
                e.Cancel = true;
            }
        }
        
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Cancelled)
                {
                    // The user canceled the operation.
                    MessageBox.Show("Operation was canceled");
                }
                else if (e.Error != null)
                {
                    // There was an error during the operation. 
                    string msg = String.Format("An error occurred: {0}", e.Error.Message);
                    MessageBox.Show(msg);
                }
                else
                {
                    // The operation completed normally. 
                    string msg = String.Format("Result = {0}", e.Result);
                    MessageBox.Show(msg);
                }
                this.Close() // Closes the form.
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-12
          相关资源
          最近更新 更多