【问题】
C#中,调试一个BackgroundWorker,发现一个问题:
DoWork在第一次执行完毕后,接下来,又进入了DoWork,
即DoWork被调用了多次。
【解决过程】
1.后来参考:
DoWork of BackgroundWorker is called twice when RunWorkerAsync is called once?
所以去看了看自己的代码,也是+=:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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); } |
所以就去把加号去掉:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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的形式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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.再去自己改为新建一个变量,而不是始终使用那个全局变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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的变量,就可以了:
1 2 3 4 5 6 7 8 9 10 11 | 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); } |