我在它工作的类中创建了一个后台工作者,但是如果我调用并等到最后一次运行,那么第二次调用它会两次执行相同的过程
我认为bw.DoWork + =有问题
private void button1_Click(object sender, EventArgs e)
{
nptest.test.start("null", "null");
}
namespace nptest
{
class test
{
public static void start(string str, string strb)
{
if (bw.IsBusy != true)
{
bw.WorkerSupportsCancellation = true;
bw.DoWork += (obj, e) => bw_DoWork(str, strb);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();
}
}
private static BackgroundWorker bw = new BackgroundWorker();
private static void bw_DoWork(string str, string strb)
{
System.Windows.Forms.MessageBox.Show("initializing BackgroundWorker");
}
private static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
Console.WriteLine("Canceled");
}
else if (!(e.Error == null))
{
Console.WriteLine("Error: " + e.Error.Message);
}
bw.Dispose();
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题解决了
class test
{
private static List<object> arguments = new List<object>();
// initializing with program startup
public static void bwinitializing()
{
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
public static void start(string str, string strb)
{
if (bw.IsBusy != true)
{
arguments.Clear();
arguments.Add(str);
arguments.Add(strb);
bw.RunWorkerAsync(arguments);
}
}
private static BackgroundWorker bw = new BackgroundWorker();
private static void bw_DoWork(object sender, DoWorkEventArgs e)
{
List<object> genericlist = e.Argument as List<object>;
System.Windows.Forms.MessageBox.Show("BackgroundWorker " + genericlist[0]);
}
Run Code Online (Sandbox Code Playgroud)
小智 16
我怀疑无意中添加了多个 DoWork事件.
也就是说,每次start调用该方法时,它都会注册一个新的 DoWork事件处理程序.这会添加并不会替换现有的处理DoWork程序处理程序.那么将有多个DoWork处理程序称为后续时间.. 1,2,3等.
// creates a NEW delegate and adds a NEW handler
bw.DoWork += (obj, e) => bw_DoWork(str, strb);
Run Code Online (Sandbox Code Playgroud)
我建议不要在这里使用闭包,而只是使用一个方法组(隐式转换为委托),然后将数据传递给RunWorkerAsync调用(有一个接受数据参数的表单).
该RunWorkerCompleted +=行没有此问题,因为它从方法组传递委托(保证始终评估为同一委托对象1).因此+=,对该行的重复调用将替换处理程序.
例:
class MyData {
public string StrA { get; set; }
}
// These only need to be setup once (and should be for clarity).
// However it will be "ok" now if they are called multiple times
// as, since the delegates are the same, the += will
// act as a replacement (as it replaces the previous delegate with itself).
bw.WorkerSupportsCancellation = true;
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
// Pass data via argument
bw.RunWorkerAsync(new MyData {
StrA = str,
});
void bw_DoWork (object sender, DoWorkEventArgs e) {
var data = (MyData)e.Argument;
var str = data.StrA;
// stuff
}
Run Code Online (Sandbox Code Playgroud)
1,我不知道这是否是保证引用等于平等,但使用这种方法允许稳定的调用+=,并-=从方法组,即使所获得的代表new DelegateType(MethodGroup).
WRT.我在主帖中的评论:如果从未创建UI元素的线程访问UI元素,那么将会有趣的"跨线程操作异常".我相信消息框的这种用法是"好的"(当不是与另一个线程的所有者一起创建时),但是在BackgroundWorker的DoWork中访问UI的做法通常是可疑的.
另外,不要bw.Dispose()在这里打电话; 将其与拥有的容器或上下文一起处理.在这种情况下它似乎很好而且温和,但只有在BGW实例永远不会再次使用时才会这样做.从事件处理程序调用它也是可疑的,因为BGW仍然"活跃".
cri*_*fan 14
我遇到了与上述评论者"Power-Mosfet"相同的问题
最后,添加一个new BackgroundWorker()然后分配给全局bw值将解决我的问题.
代码是,改为:
private BackgroundWorker gBgwDownload;
private void yourFunction_bw(xxx)
{
// Create a background thread
gBgwDownload.DoWork += bgwDownload_DoWork;
gBgwDownload.RunWorkerCompleted += bgwDownload_RunWorkerCompleted;
//omited some code
gBgwDownload.RunWorkerAsync(paraObj);
}
Run Code Online (Sandbox Code Playgroud)
至:
private BackgroundWorker gBgwDownload;
private void yourFunction_bw(xxx)
{
// Create a background thread
gBgwDownload = new BackgroundWorker(); /* added this line will fix problem */
gBgwDownload.DoWork += bgwDownload_DoWork;
gBgwDownload.RunWorkerCompleted += bgwDownload_RunWorkerCompleted;
//omited some code
gBgwDownload.RunWorkerAsync(paraObj);
}
Run Code Online (Sandbox Code Playgroud)
还有另一个原因.DoWorkEventHandler在其生成的代码中查找InitializeComponent()如果您通过compnent UI属性生成它并自己注册它.
因为如果你再次注册它,它将不会覆盖前一个,但会添加另一个事件,并将调用两次.