1

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

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

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

我尝试过使用AutoResetEventWaitOne但这(无论出于何种原因)仍然不起作用。

有没有其他方法可以在不冻结主 UI 线程的情况下等待 BW 完成?

4

4 回答 4

1

如果你不想阻塞 UI 直到等待事件(所以我你会做点什么)你可以在结束时引发一个事件DoWork(),并且 UI 线程可以接收它。

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

代码可能如下所示:

   Action action =(() => DoWorkMethod());
   Task.Factory.StartNew(() => action()).ContinueWith(()=>CallAfterComplete());
于 2012-05-18T09:39:57.240 回答
1

您还可以使用本例中的任务

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();
    }
}
于 2012-05-18T09:44:57.217 回答
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 进度示例。

于 2012-05-18T10:25:40.947 回答
0

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

于 2012-05-18T09:46:52.140 回答