C#中BackgroundWorker中的DoWork执行了多次

【问题】

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);
}
当使用C#中的ProgressBar和BackgroundWorker结合使用时,可以实现在后台执行耗时操作并显示进度条的功能。以下是一个示例: ```sharp using System; using System.ComponentModel; using System.Threading; using System.Windows.Forms; namespace ProgressBarBackgroundWorkerExample { public partial class MainForm : Form { private BackgroundWorker backgroundWorker; public MainForm() { InitializeComponent(); // 初始化BackgroundWorker backgroundWorker = new BackgroundWorker(); backgroundWorker.WorkerReportsProgress = true; backgroundWorker.DoWork += BackgroundWorker_DoWork; backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged; backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted; } private void btnStart_Click(object sender, EventArgs e) { // 禁用开始按钮,防止多次点击 btnStart.Enabled = false; // 启动后台操作 backgroundWorker.RunWorkerAsync(); } private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { // 模拟一个耗时的操作 for (int i = 0; i <= 100; i++) { // 执行耗时操作 // ... // 报告进度给BackgroundWorker backgroundWorker.ReportProgress(i); // 等待一段时间,模拟实际操作 Thread.Sleep(50); } } private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { // 更新进度条的当前值 progressBar.Value = e.ProgressPercentage; } private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // 后台操作完成后的处理 // ... // 启用开始按钮 btnStart.Enabled = true; MessageBox.Show("操作完成!"); } } } ``` 在上述示例中,我们创建了一个Windows窗体应用程序,其中包含一个ProgressBar控件和一个开始按钮。当点击开始按钮时,后台操作会在BackgroundWorker执行,同时通过ReportProgress方法报告进度,进度条会实时更新。当后台操作完成后,会触发RunWorkerCompleted事件进行后续处理。 请注意,以上示例仅为演示ProgressBar与BackgroundWorker的结合使用,并没有实际的耗时操作。你可以根据实际需求修改DoWork事件中的耗时操作代码。希望对你有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值