0

下面是我的编码:

    Form2 msgForm;
    private void button3_Click_1(object sender, EventArgs e)
    {

        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

        msgForm = new Form2();

        try
        {
            bw.RunWorkerAsync();

            msgForm.ShowDialog();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        // Coding that transmit protocol and will last around 2 minutes.
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        msgForm.Close();
    }

每次单击按钮以传输持续约 2 分钟的协议时,我都会使用后台工作程序方法。在传输过程中,From2 将显示“请稍候”。

但是我在使用这种编码时遇到了一些问题。问题是,当我第一次单击按钮时,它会传输一次协议。之后我再次单击,这是第二次,它传输了两次协议。之后我再次点击,这是第三次,它传输协议3次......等等。每次单击按钮时,传输协议的次数都会增加。

每次我单击按钮时,它不是只会运行一次 void bw_DoWork 中的编码吗?

我的编码有问题吗?

4

4 回答 4

6

每次单击时,您都会附加一个额外的处理程序,然后它会与您之前添加的所有内容一起运行,并保持在原处(因为对象仍然存在,您正在重新使用它)。

要解决此问题,您需要:

  • 将后台工作者的声明移到方法中(所以每次都是新的,只有一个DoWork处理程序

像这样:

private void button3_Click_1(object sender, EventArgs e)
{
    BackgroundWorker bw = new BackgroundWorker();
    // rest of your code
}
  • 在类的构造函数中移动.DoWork += ...附加处理程序的

这主要取决于您是否在其他地方使用该工人。

于 2012-09-20T07:13:47.783 回答
0

看起来每次点击都会有一个新的工作人员开始。为避免这种行为,请在再次启动之前检查工作人员是否正忙。

try
{
    if (!bw.IsBusy)
        bw.RunWorkerAsync();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

并且您可以在后台工作人员执行其工作时禁用该按钮,button3.Enabled = false;然后在该方法中重新启用它bw_RunWorkerCompleted,让用户了解他必须等待并且在该过程完成之前不能再次单击。

于 2012-09-20T07:15:28.813 回答
0

首先确保您的列表/收藏在传输代码之前是清晰的。然后在你的源代码中使用 BreakPoint 并记住你的 BackgroundWorker 不能运行两次或更多次,因为你使用了 ShowDialog。

于 2012-09-20T07:18:12.097 回答
0

检查工人是否忙:

    if (!bw.IsBusy)         
    bw.RunWorkerAsync(); 

在执行过程时,我还将禁用该按钮并将文本更改为例如“正在运行”。

使用 bw_RunWorkerCompleted 方法事件调用,然后重新启用按钮并更改文本。此方法与 UI 在同一线程上运行,因此不存在跨线程问题。

在您的设计中,为什么要显示“请稍候”通知的另一种形式?我建议在异步进程开始之前更新现有表单上的标签(因此不是跨线程 UI 问题),或者如果您需要在之后更新,则可以使用以下内容:

lblNotify.Invoke(new Action(() => lblNotify.Text = @"Please wait"));

然后,上面将允许您在主线程上运行您的请求。

于 2012-09-20T09:47:29.507 回答