等待BackgroundWorker完成?

时间:2012-05-18 09:34:36

标签: c# .net multithreading visual-studio-2010 backgroundworker

我有2个异步进程,需要一个接一个地调用(一个是XML创建backgroundworker,另一个是raring BW,它使用在第一个过程)。这些线程的主要原因是停止UI冻结并通过进度条的方式提供状态更新 - 因为这样的同步方法是不可取的/可能的。

if (!CreateXMLBW.IsBusy)
{
CreateXMLBW.RunWorkerAsync("");
}
if (!CreateRarBW.IsBusy)
{
CreateRarBW.RunWorkerAsync();
}

我无法将第二个BW放在第一个完成事件中,因为这些进程可以单独使用,因此如果我只想创建XML文件,我可以这样做。

我尝试过使用AutoResetEventWaitOne,但这(无论出于何种原因)仍无效。

有没有其他方法可以等待BW完成而不冻结主UI线程?

4 个答案:

答案 0 :(得分:1)

如果你不想在等待事件之前阻止UI(所以我假设你要做某事) 你可以在DoWork()结束时引发事件,UI线程可以接收它。

如果您使用的是4.0并且可以避免使用BackgroundWorker,则可以使用TPL中的Task.ContinueWith

伪代码可能如下所示:

   Action action =(() => DoWorkMethod());
   Task.Factory.StartNew(() => action()).ContinueWith(()=>CallAfterComplete());

答案 1 :(得分:1)

您也可以在此示例中使用Task

class Program
{
    static XElement CreateXml()
    {
        System.Threading.Thread.Sleep(1000);
        return XElement.Parse(@"<FooBar>Hi!</FooBar>");
    }

    static void ProceedXml(XElement xml)
    {
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine(xml.ToString());
    }

    public static void Main()
    {
        Task.Factory.StartNew<XElement>(CreateXml)
                    .ContinueWith(t => ProceedXml(t.Result));
        Console.ReadKey();
    }
}

答案 2 :(得分:1)

您的方案正是Task的设计目标。在您的特定情况下,您的代码可能如下所示:

public delegate void UpdateUI(int progress);

private void RunOneAfterAnotherAsync()
{
    Task<XmlElement> task = Task.Factory.StartNew<XmlElement>(CreateXMLBW);
    task.ContinueWith(CreateRarBW);
}

private XmlElement CreateXMLBW()
{
    // your code

    // progress
    progressBar1.Invoke((UpdateUI)UpdateProgressBar, new object[] {progressValue});

    // result
    XmlDocument doc = new XmlDocument();
    return doc.CreateElement("element");
}

private void CreateRarBW(Task<XmlElement> task)
{
    CreateRarBW(task.Result);
}

private void CreateRarBW(XmlElement arg)
{
    // your code
}

public void UpdateProgressBar(int value)
{
    this.progressBar1.Value = value;
}

RunOneAfterAnotherAsync没有阻塞,你的2个方法一个接一个地异步运行。 CreateRarBW仅在CreateXMLBW结束且没有例外的情况下运行,但您可以通过在ContinueWith中使用其他参数来更改它。

您可以做的远不止这个示例节目 - 我鼓励您探索Task课程。

编辑

我已经稍微扩展了一些示例,以便将从第一个任务传递到第二个任务的结果合并到第二个任务中。还添加了UI进度示例。

答案 3 :(得分:0)

您的UI可以处理第一个BW上的RunWorkerCompleted事件并调用第二个BW。