【问题】
C#中,调试一个BackgroundWorker,发现一个问题:
DoWork在第一次执行完毕后,接下来,又进入了DoWork,
即DoWork被调用了多次。
【解决过程】
1.后来参考:
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); }