2012-09-20 51 views
0

下面是我的编码:C#BackgroundWorker的继续运行DoWork的

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将显示“Please wait”。

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

是不是说它只会运行一次无效的编码bw_DoWork每次我点击按钮?

我的编码有问题吗?

回答

6

要追加每次点击时间额外处理程序,然后它的运行与你之前添加的一切,它保持它(因为对象仍然存在,你在那里沿着再利用它)。

为了解决这个问题,你需要:

  • 移动的方法中后台工作人员的声明(所以它的新的每一次,只有一个DoWork处理

就像这样:

private void button3_Click_1(object sender, EventArgs e) 
{ 
    BackgroundWorker bw = new BackgroundWorker(); 
    // rest of your code 
} 
  • 移动该追加小时.DoWork += ...安德勒在类的构造函数

它主要取决于如果您在其他地方使用该工作。

+0

没有亚历克斯。我只是使用工作人员传输协议而已。 – Coolguy

+0

然后在方法中声明它。 – Alex

+0

亚历克斯,你是指通过移动方法内的后台工作者的声明是什么意思? – Coolguy

0

它看起来像一个新的工人开始每一次点击。 为避免这种情况,请在再次启动之前检查工作人员是否忙碌。

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

虽然BackgroundWorker的,它的工作,通过button3.Enabled = false;,您可以禁用按钮重新启用它在bw_RunWorkerCompleted方法,让用户明白,他必须等待,直到该过程完成后无法再次点击。

+1

没有。他每次都追加另一个处理程序。 – Alex

+0

@Alex我仔细检查了这个问题,你说得对,我错过了这一点。 upvoted你的答案。无论如何,我认为检查BackgroundWorker是否已在运行并相应地启用/禁用按钮是一个好主意=) –

0

首先确保您的列表/集合在传输代码之前已清除。 然后在您的源代码中使用BreakPoint,并记住您的BackgroundWorker无法运行两次或更多,因为您使用ShowDialog。

0

检查工人忙:

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

我还要禁用按钮并更改文本如“运行”,而进程正在excecuted。

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

在您的设计上,为什么您会显示另一个表单以显示“请稍等”通知?我建议你现有的形式更新的标签或者异步过程开始之前(所以不能跨线程UI的问题),或者如果你需要后更新,那么你可以使用以下命令:

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

上述随后将允许你在主线程上运行你的请求。