问题是什么:
我有一个wpf应用程序,有一个功能"安装"分配给一个按钮。它复制并删除一些文件。在button_click功能中,我检查是否"安装"可以运行,如果可以,我可以运行它。这个函数在另一个类中,所以我通过以下方式运行它:
class1 class = new class1();
class.function();
,功能是:
public void install()
{
worker.RunWorkerAsync();
worker.WorkerSupportsCancellation = true;
worker.WorkerReportsProgress = true;
worker.DoWork += (s, args) =>
{
for(int i=0;i<100;i++)
{
//do some work;
worker.ReportProgress(i);
}
MessageBox.Show("done");
};
worker.ProgressChanged += (s, args) =>
{
// report progress
};
worker.RunWorkerCompleted += (s, args) =>
{
worker.CancelAsync(); //not sure if it's needed, it changes nothing
//reset some values
};
}
是的,类似的东西。很抱歉,如果它看起来有点迟钝但我在这里仍然学习如何粘贴代码元素:P(如果需要我可以上传整个项目或者粘贴一些部分)
整件事情很有效,但是当我点击第二,第三,......的第二次安装按钮时,第n次工作人员正在进行n次工作(参见线程名称)。我没有想法为什么。 我错过了像worker.close()或其他什么东西吗?
编辑:http://pastebin.com/YR9ZHCCY&lt; - 这里看起来好多了
答案 0 :(得分:2)
每次处理按钮单击时,都会将您的worker方法订阅到DoWork
事件。在C#中,委托是&#34; multicast&#34;,这意味着它们可以有多个调用目标。每次订阅worker方法时,都会添加一个调用目标,从而导致该方法被称为额外的时间。因此,对于按下N按钮,您将在DoWork
事件委托中获得相同调用目标方法的N个副本。
与其他活动ProgressChanged
和RunWorkerCompleted
相同。
如果要保留持久性BackgroundWorker
实例,则应在初始化时将其配置一次(例如,通过在Visual Studio Designer中设置属性和事件)。如果要在每次单击按钮时重新配置它,则不应保留持久BackgroundWorker
实例。
例如,俗气的方法,将其添加到install()
方法的开头:
if (worker != null)
{
worker.Dispose();
}
worker = new BackgroundWorker();
非俗气的方法包括找到BackgroundWorker对象的初始化并将所有初始化放在那里。我不知道这是如何在WPF设计器UI中显示的......在Forms中,您在所有者表单的设计窗口底部获得了一个BackgroundWorker组件;您可以单击该组件,然后通过“属性”窗口编辑属性和事件处理程序。