BackgroundWorker到底是如何工作的

本文关键字:工作 何工作 BackgroundWorker | 更新日期: 2023-09-27 18:03:53

我为Message Receiving类编写了这段代码,该类使用后台工作者检查目录中的新文件(这些文件是从不断更新的用户接收到的SMS消息)。如果目录不为空,我将向每个新SMS发送确认消息并再次启动worker。

 public MessageReceiving()
    {
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);           
    }
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {   
        if(e.Result == true)
        { 
        SendAcknowledgement();
        if(!bw.IsBusy)
            bw.RunWorkerAsync();
        }
    }
void bw_DoWork(object sender, DoWorkEventArgs e)
    {
       bool flag = false;
        while (flag.Equals(false))
        {
            string path = @"C:'SMS";
            if (Directory.GetFiles(path).Length > 0)
            {
                e.Result = true;
                flag = true;
            }
            else
            {
                e.Result = false;
            }
        }
    }

我从主线程初始化工作线程一次-

MessageReceiving mr = new MessageReceiving();
mr.bw.RunWorkerAsync();

我所做的一切都是为了让我能够同步地向用户发送消息——一旦用户发送了一条SMS,我就会向他发送一个ACK。问题是用户即使发送一条短信也会收到多个ack -为什么会发生这种情况?所有的可能性我都想过了,但都无济于事!

BackgroundWorker到底是如何工作的

考虑当它开始时会发生什么:

  • 开始运行bw_DoWork
  • 然后循环(不是一个好主意开始),直到它找到一个文件
  • 后台工作完成,你发送一个确认
  • 然后立即再次运行后台工作线程…它将再次找到该文件,除非您在SendAcknowledgement期间删除了该文件。有你吗?

怀疑你真正想要的是什么而不是顺便说一下,任何都是FileSystemWatcher。还要注意,仅仅因为文件存在并不意味着它已经完成写入,或者您可以读取它。

另外,你的紧循环可以变得更简单:

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    string path = @"C:'SMS";
    while (!e.Result)
    {
        e.Result = Directory.GetFiles(path).Any();
    }
}

和我也会改变

if (e.Result == true)

if (e.Result)

(假设e.Result类型为bool;如果不是,则说明当前代码存在其他问题。

这取决于未显示的代码。

您最多需要1个线程扫描文件。然后在处理过程中的某个地方,您必须删除或重命名文件。在您的情况下,这应该发生在SendAcknowledgement中,并且在发送所有回复之前不应该重新启动Bgw。

最好尽早使用重命名文件并将它们放入队列中。或者在DoWork中找到文件后直接处理它们。SendAcknowledgement(fileName)看起来更符合逻辑。

当前你的SendAcknowledgement()运行在主线程中,这可能不是你想要的。