【问题】
C#中,调试一个BackgroundWorker,发现一个问题:
DoWork在第一次执行完毕后,接下来,又进入了DoWork,
即DoWork被调用了多次。
【解决过程】
1.后来参考:
https://stackoverflow.com/questions/12231379/dowork-of-backgroundworker-is-called-twice-when-runworkerasync-is-called-once
所以去看了看自己的代码,也是+=:
private void getUrlRespStreamBytes_bw(ref Byte[] respBytesBuf,
string url,
Dictionary<string, string> headerDict,
Dictionary<string, string> postDict,
int timeout,
Action<int> funcUpdateProgress)
{
// Create a background thread
gBgwDownload.DoWork += new DoWorkEventHandler(bgwDownload_DoWork);
gBgwDownload.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgwDownload_RunWorkerCompleted);
gBgwDownload.WorkerReportsProgress = true;
gBgwDownload.ProgressChanged += new ProgressChangedEventHandler(bgwDownload_ProgressChanged);
//init
bNotCompleted_download = true;
gFuncUpdateProgress = funcUpdateProgress;
// run in another thread
object paraObj = new object[] {respBytesBuf, url, headerDict, postDict, timeout};
gBgwDownload.RunWorkerAsync(paraObj);
}
所以就去把加号去掉:
private void getUrlRespStreamBytes_bw(ref Byte[] respBytesBuf,
string url,
Dictionary<string, string> headerDict,
Dictionary<string, string> postDict,
int timeout,
Action<int> funcUpdateProgress)
{
// Create a background thread
gBgwDownload.DoWork = new DoWorkEventHandler(bgwDownload_DoWork);
gBgwDownload.RunWorkerCompleted = new RunWorkerCompletedEventHandler(bgwDownload_RunWorkerCompleted);
gBgwDownload.WorkerReportsProgress = true;
gBgwDownload.ProgressChanged = new ProgressChangedEventHandler(bgwDownload_ProgressChanged);
//init
bNotCompleted_download = true;
gFuncUpdateProgress = funcUpdateProgress;
// run in another thread
object paraObj = new object[] {respBytesBuf, url, headerDict, postDict, timeout};
gBgwDownload.RunWorkerAsync(paraObj);
}
试试结果。
结果却是,直接语法错误,都无法运行。
2.同样参考上贴,去改为,去掉new handler的形式:
private void getUrlRespStreamBytes_bw(ref Byte[] respBytesBuf,
string url,
Dictionary<string, string> headerDict,
Dictionary<string, string> postDict,
int timeout,
Action<int> funcUpdateProgress)
{
// Create a background thread
gBgwDownload.DoWork += bgwDownload_DoWork;
gBgwDownload.RunWorkerCompleted += bgwDownload_RunWorkerCompleted;
gBgwDownload.WorkerReportsProgress = true;
gBgwDownload.ProgressChanged += bgwDownload_ProgressChanged;
//init
bNotCompleted_download = true;
gFuncUpdateProgress = funcUpdateProgress;
// run in another thread
object paraObj = new object[] {respBytesBuf, url, headerDict, postDict, timeout};
gBgwDownload.RunWorkerAsync(paraObj);
}
试试结果,结果问题依旧。
第二次调用DoWork后,紧接着,还是直接进入DoWork,而不是重新执行别的函数。
3.再去自己改为新建一个变量,而不是始终使用那个全局变量:
private void getUrlRespStreamBytes_bw(ref Byte[] respBytesBuf,
string url,
Dictionary<string, string> headerDict,
Dictionary<string, string> postDict,
int timeout,
Action<int> funcUpdateProgress)
{
// Create a background thread
gBgwDownload = new BackgroundWorker();
gBgwDownload.DoWork += bgwDownload_DoWork;
gBgwDownload.RunWorkerCompleted += bgwDownload_RunWorkerCompleted;
gBgwDownload.WorkerReportsProgress = true;
gBgwDownload.ProgressChanged += bgwDownload_ProgressChanged;
//init
bNotCompleted_download = true;
gFuncUpdateProgress = funcUpdateProgress;
// run in another thread
object paraObj = new object[] {respBytesBuf, url, headerDict, postDict, timeout};
gBgwDownload.RunWorkerAsync(paraObj);
}
试试,结果就可以了。
【总结】
BackgroundWorker的DoWork被执行多次,原因是
之前BackgroundWorker初始化的时候,DoWork赋值时,都是
new DoWorkEventHandler
的形式,所以每次都新加了个DoWork动作,所以会导致后续多次调用时,被执行多次。
另外,不能每次都
gBgwValue += xx_doWork;
否则,也还是会多把后续的多次的DoWork都加到同一个全局变量gBgwValue上,导致后续DoWork被多次调用执行;
最终,改为,不带new DoWorkEventHandler的,每次是新建一个BackgroundWorker的变量,就可以了:
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);
}