繁体   English   中英

C#BackgroundWorker ProgressChanged在函数结束之前不会被解雇

[英]C# BackgroundWorker ProgressChanged doesn't get fired until end of function

我的班上有一个内部有一些循环的方法。 此方法的主要目的是转换一些文件,因此我在表单中放置了一个进度条,该进度条在转换完每个文件后应进行更新。

我尝试了所有可能的组合,并且阅读了所有可能的内容,但无法解决此问题。

void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    converterProgressBar.Value = e.ProgressPercentage;
}

仅在执行方法的主循环之后才调用。

这是我的方法:

public string Convert()
{
    convertBtn.Enabled = false;
    bw.WorkerReportsProgress = true;
    bw.WorkerSupportsCancellation = true;

    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
    totalCount = files.length;
    bw.RunWorkerAsync();

    if (!Directory.Exists(folder))
    {
        Directory.CreateDirectory(folder);
    }
    foreach (string file in files)
    {
        countFile++;
        if (chk.Checked)
        {
            class1.DoJob();
        }

        using (// some code))
        {
            using (//some other code))
            {
                try
                {
                    using (// again some code)
                    {
                        // job executing
                    }
                }
                catch (exception
                {

                }   
            }
        }
        convertedVideosL.Text = txtToUpdate;
        convertedVideosL.Refresh();
    }
    countFile = countFile + 1;
    MessageBox.Show("Done");
    countFile = -1;
    return outputFile;
}

这是BackgroundWorker事件处理程序:

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i <= totalCount; i++)
    {
        if (bw.CancellationPending)
        {
            e.Cancel = true;
        }
        else
        {
            int progress = Convert.ToInt32(i * 100 / totalCount);
            (sender as BackgroundWorker).ReportProgress(progress, i);
        }
    }
}

void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    converterProgressBar.Value = e.ProgressPercentage;
}

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled == false)
    {
        convertedVideosL.Text = "Finished!";
    }
    else
    {
        convertedVideosL.Text = "Operation has been cancelled!";
    }
}

但是我无法为每个转换的文件更新进度条。 它等待foreach循环结束,然后调用bw_ProgressChanged

如果将RunWorkerAsync()放在foreach循环中,则会引发异常,该异常表示BackgroundWorker忙于执行其他任务。

在我看来,很明显DoWork()仅执行for循环,然后它不应该知道正在进行的转换,但是ProgressChanged应该由ReportProgress(progress,i)触发。

请问有人能解释我为什么,并帮助我解决问题吗?

谢谢!

当前,转换不是由BackgroundWorker类型的实例执行的。 应该从DoWork事件处理程序中调用转换。

请考虑提取与转换相关的功能:

if (!Directory.Exists(folder))
{
    Directory.CreateDirectory(folder);
}
foreach (string file in files)
{
    // Details...
}

进入单独的方法。 之后,只需从DoWork事件处理程序中调用该方法即可。

伪代码演示了这个想法:

public void StartConversion()
{
    ...
    TWorkerArgument workerArgument = ...;
    worker.RunWorkerAsync(workerArgument);
    // No message box here because of asynchronous execution (please see below).
}

private void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{   
    // Get the BackgroundWorker that raised this event.
    BackgroundWorker worker = sender as BackgroundWorker;
    e.Result = Convert(worker, (TWorkerArgument)e.Argument);
}

private static TWorkerResult Convert(BackgroundWorker worker, TWorkerArgument workerArgument)
{
    if (!Directory.Exists(folder))
    {
        Directory.CreateDirectory(folder);
    }

    foreach (string file in files)
    {
        // Details...
        worker.ReportProgress(percentComplete);
    }

    return ...;
}

private void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Show the message box here if required.
}

请适当地替换TWorkerArgumentTWorkerResult类型。

另外,请参考使用BackgroundWorker类的示例以获取更多详细信息: 如何:实现使用后台操作的表单MSDN

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM