C# backgroundWorker停止工作时关闭表单

C# backgroundWorker停止工作时关闭表单,c#,multithreading,backgroundworker,C#,Multithreading,Backgroundworker,我正在开发一个应用程序,可以从Mifare智能卡读取数据。我必须创建一个表单,定期检查Mifare读卡器,当卡在范围内时,读取其序列号并将其发送到父表单。我设法让后台工作人员读取序列号,但我无法从中关闭表单,因为它会导致跨线程调用错误。是否有方法监视backGroundWorker所做的工作,以及当它成功读取卡ID时,停止它并关闭子窗体? 这是我在DoWork方法中使用的代码: private void backgroundWorker1_DoWork(object sender, DoWork

我正在开发一个应用程序,可以从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变量是否在主线程中更改其值,如果更改,请关闭窗体。
我试图通过使用计时器来解决这个问题,但当我这样做时,计时器会阻塞主窗体线程,我无法手动关闭它(当然我必须能够)。你能提出一个解决这个问题的方法吗?

你可以编写你的BackgroundWorker,这样它完成工作后就会返回


然后在主窗体中,订阅并适当响应,大概只需关闭窗体即可。

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

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


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

从backgroundWorker添加
RunWorkerCompleted
事件:

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

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

正如其他人提到的,下面是如何实现
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.
    }

在DoWork事件处理程序中调用CancelAsync()没有什么意义。只需使用break来中断while()循环。在RunworkerCompleted事件处理程序中关闭窗口很简单。更难解决的问题是当用户在工作人员完成之前关闭窗口时该怎么办。不要忽视这一点。勾选Ok,但我如何向BackgroundWorker“解释”他已经完成(这是我第一次与BackgroundWorker合作,请耐心等待)。逻辑上,当CardID从“0”或string.Empty更改为某个数字时,他的任务就完成了。发生这种情况时,我如何告诉后台工作人员他应该完成其工作?这是您在
DoWork
方法中定义的。在OP中使用的
while
语句定义了循环将退出且方法将返回的点。现在,您正在等待取消该过程。当DoWork方法结束时,BackgroundWorker将认为其工作已完成,并且将触发RunWorkerCompleted事件。