【问题标题】:backgroundworker vs Event后台工作者与事件
【发布时间】:2012-03-29 22:58:30
【问题描述】:

我正在使用我的 Winform 应用程序将数据包缓冲区发送到我的网卡,我的应用程序显示通过进度条进行,如果我选择在数据包之间没有任何延迟地发送所有缓冲区,我的应用程序卡住了(变成灰色)并仅在发送所有缓冲区后才恢复正常行为(以防我的缓冲区非常大,例如 > 50,000 个数据包) 那么我该如何处理这种情况呢?或许可以通过事件更改检查我所有类属性(发送数据包的数量等)的后台工作人员?

    listBoxFiles.SetSelected(0, true);
    bgWoSingle = new BackgroundWorker();
    bgWoSingle.WorkerReportsProgress = true;
    bgWoSingle.ProgressChanged += new ProgressChangedEventHandler(bgW_ProgressChanged);
    bgWoSingle.DoWork += new DoWorkEventHandler(
    (s3, e3) =>
    {
        while (loopsCount < numberOfLoops && bContinuePlay && ifContinue)
        {
            for (int i = 0; (i < listBoxFiles.Items.Count) && bContinuePlay && ifContinue; i++)
            {
                this.Invoke((MethodInvoker)delegate
                {
                    lbCurrentFileNum.Text = "(" + (i + 1) + "/" + listBoxFiles.Items.Count + "):";
                });

                string path = (string)listBoxFiles.Items[i];
                pcap = new Pcap(path, playSpeed, isSync);
                pcap._startTimer += new EventHandler(pcap_packetStartTimer);
                pcap._stopTimer += new EventHandler(pcap__packetStopTimer);
                pcap.evePacketProgress += new Pcap.dlgPacketProgress(
                    (progressCount) =>
                    {
                        pcap._fileSelectedIndex = i;
                        bgWoSingle.ReportProgress(progressCount, pcap);
                    });

                if (selectedAdapter != null)
                {
                    //play the file
                    bContinuePlay = pcap.playCapture(selectedAdapter._packetDevice);                     }
            }

            loopsCount++;
        }

    bgWoSingle.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
        (s3, e3) =>
        {

        }
        );

    bgWoSingle.RunWorkerAsync();

这里我检查类属性(类名是 pcap):

void bgW_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    //check the properties and update the UI
    labelPacketSent.Text = pcap._numberOfSendPackets.ToString("#,##0"); 
    progressBar1.Value = e.ProgressPercentage;
}

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    您必须为此使用 BackGroundWorker。我正在为它添加一个小例子。

    private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
          backgroundWorker.ReportProgress(80, 15000);
    }
    
    private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
         var numberOfPackets = int.parse(e.UserState);
    
         MessageBox.Show("Percentage: " + e.ProgressPercentage );
         MessageBox.Show("Packets sent :" + numberOfPackets);  
    }
    

    worker 可以通过 UserState 发送完成百分比或您想要的任何其他数据。

    【讨论】:

    • 目前我的BackgroundWorker来自主线程并检查发送数据包的calss
    • 看看我的更新,你能告诉我怎么做你的意思吗?
    • 您所要做的就是 typeCast。 var pcapInstance = (Pcap)e.UserState;现在您可以访问整个数据。这是你想要的吗?
    • 我只希望应用程序不会卡住,如果数据包速率太快,应用程序会变灰,只有当它完成后,GUI才能再次启用
    • 您为什么如此频繁地触发 ReportProgress?为什么不触发事件可能是每 n 个数据包?
    【解决方案2】:

    这个想法是有一个使用 BGWorker 的 PacketSender 类,并注册到它的 Progress 事件等,并具有一个或多个自身的 progress 属性,以允许绑定/侦听。

    然后,PacketSender 类将收到一些大任务要做,并让 BGWorker 去做。您的 BGWorker-Work 方法将在一个单独的线程上,每次您从其中调用 ReportProgress 时,您都会在主线程中 PacketSender 的侦听方法中获取它,并且能够将其向上冒泡到 PacketSender.ProgressChanged 侦听器或更改完成百分比的 ProgressChanged 属性等。

    正确的方法是在 PacketSender ctor 中获取任务的数据,并立即启动 BGWorker,以防止在同一个 PacketSender 上执行多个任务,或者使用 Start 和 Stop 方法检查是否BGWorker 正在工作,并将防止对单个 PacketSender 进行多任务处理。

    【讨论】:

      【解决方案3】:

      这里最好使用 BackgroundWorker。它比定义自定义事件来更新进度条更新颖且更好。检查MSDN

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-29
        • 1970-01-01
        • 2014-03-10
        • 2011-10-30
        • 2011-03-17
        相关资源
        最近更新 更多