救命。我确实重用了BackgroundWorker。但工人发生了非常奇怪的行为

时间:2011-07-24 18:45:19

标签: c# wpf multithreading backgroundworker

帮助。

我确实重用了BackgroundWorker。但工人发生了非常奇怪的行为。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    //(!)note bw created at class scope, not button1_click.
    BackgroundWorker bw = new BackgroundWorker();

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        bw.DoWork+=new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        bw.RunWorkerAsync();
        System.Console.Beep(2000, 200);
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        System.Console.Beep(1000, 200);
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        System.Console.Beep(2500, 200);
    }

}

它发生了非常奇怪的行为。

我预计的嘟嘟声序列是嘟嘟声(200,200) - 哔(1000,200) - 哔(2500,200)。

是肯定的。它做了。但这是第一次。

*beep(200,200)=A
*beep(1000,200)=B
*beep(2500,200)=C

[when i click then button1 in second time]
A-B-B-C-C

[when i click then button1 in third time]
A-B-B-B-C-C-C

[when i click then button1 in fourth time]
A-B-B-B-B-C-C-C-C

???

这是什么意思?

(*原因,当我的BackgroundWorker bw = new BackgroundWorker();移到button1_click的第一行,它正常工作)

2 个答案:

答案 0 :(得分:4)

每次单击该按钮时,您都会将另一个处理程序添加到DoWorkRunWorkerCompleted事件中 - 这样当您再次调用这些代理时致电RunWorkerAsync

就个人而言,我建议你在每次点击时创建一个后台工作者 - 但是如果必须重复使用它,只需附加一次事件处理程序(例如在构造函数中)。

答案 1 :(得分:1)

原因是.NET中的事件是多播的。

每次执行这段代码时,按下按钮单击事件:

button1.Click += ...

您将另一个事件处理程序添加到该点击事件中。

因此,第一次执行上面的代码,然后单击按钮时,您的事件处理程序将被调用一次。

然后,如果再次调用上面的代码 ,然后单击该按钮,则会调用两次事件处理程序。然后是三次,四次,依此类推。

因此,如果您打算重用BackgroundWorker对象,请不要执行多次添加这两个事件处理程序的代码,您应该没问题。

理想情况下,我会在构建BackgroundWorker对象的同时附加事件处理程序,然后仅在按钮单击时调用.RunWorkerAsync。但是,正如乔恩所提到的,你应该考虑一下你是否应该重用。如果单击该按钮并尝试在工作程序运行时启动该工作程序,则会出现异常。