5

我想我在这里遗漏了一些明显的东西,但是在使用任务和检索值时如何更新 GUI?(我正在尝试使用等待/异步而不是 BackgroundWorker)

在我的控件上,用户单击了一个按钮,该按钮将执行一些需要时间的操作。我想提醒父表单,以便它可以显示一些进度:

private void ButtonClicked()
        {
            var task = Task<bool>.Factory.StartNew(() =>
            {
                WorkStarted(this, new EventArgs());
                Thread.Sleep(5000);
                WorkComplete(this, null);
                return true;
            });

            if (task.Result) MessageBox.Show("Success!");//this line causes app to block
        }

在我的父表单中,我正在收听 WorkStarted 和 WorkComplete 以更新状态栏:

myControl.WorkStarting += (o, args) =>
                {
                    Invoke((MethodInvoker) delegate
                        {
                            toolStripProgressBar1.Visible = true;
                            toolStripStatusLabel1.Text = "Busy";
                        });

                };

如果我错了,请纠正我,但应用程序挂起,因为“Invoke”正在等待 GUI 线程可用,直到我的“ButtonClicked()”调用完成。所以我们陷入了僵局。解决这个问题的正确方法是什么?

4

2 回答 2

2

您正在阻塞 UI 线程Task.Result阻塞,直到任务完成。

尝试这个。

private async void ButtonClicked()
{
     var task = Task<bool>.Factory.StartNew(() =>
     {
            WorkStarted(this, new EventArgs());
            Thread.Sleep(5000);
            WorkComplete(this, null);
            return true;
     });

     await task;//Wait Asynchronously
     if (task.Result) MessageBox.Show("Success!");//this line causes app to block
}
于 2013-10-02T14:36:40.227 回答
1

您可以使用Task.Run在后台线程上执行代码。基于任务的异步模式指定进度更新的模式,如下所示:

private async void ButtonClicked()
{
  var progress = new Progress<int>(update =>
  {
    // Apply "update" to the UI
  });
  var result = await Task.Run(() => DoWork(progress));
  if (result) MessageBox.Show("Success!");
}

private static bool DoWork(IProgress<int> progress)
{
  for (int i = 0; i != 5; ++i)
  {
    if (progress != null)
      progress.Report(i);
    Thread.Sleep(1000);
  }
  return true;
}

如果您的目标是 .NET 4.0,那么您可以使用Microsoft.Bcl.Async; 在这种情况下,您将不得不使用TaskEx.Run而不是Task.Run. 我在我的博客上解释了为什么你不应该使用Task.Factory.StartNew.

于 2013-10-02T14:51:11.287 回答