使用 async 而不是 Task.Run()

Con*_*Guy 3 c# async-await

我有以下一段代码:

private void btnAction_Click(object sender, RoutedEventArgs e)
{

    /** Clear the results field */
    txtResult.Text = "";

    /** Disable the button and show waiting status */
    btnAction.IsEnabled = false;
    lblStatus.Text = "Wait...";

    /** Get input from the query field */
    string input = query.Text;

    /** Run a new task */
    Task.Run(() => {

        // calling a method that takes a long time (>3s) to finish and return
        var attempt = someLibrary.doSomethingWith(input);

        // return the result to the GUI thred
        this.Dispatcher.Invoke(() =>
        {

            if (attempt.ContainsKey("success"))
            {
                if (attempt["success"] == true)
                {
                    txtResult.Text = "Success! The door is: " + (attempt["is_open"] ? "open" : "closed");
                    lblStatus.Text = "";
                }
                else
                {
                    lblStatus.Text = "Error! The service says: " + attempt["errorMessage"];
                }
            }

            else
            {
                MessageBox.Show("There was a problem getting results from web service.");
                lblStatus.Text = "";
            }

            /** Re-enable the button */
            btnAction.IsEnabled = true;

        });
    });

}
Run Code Online (Sandbox Code Playgroud)

现在,我想:

  • 以使用回调而不是使用的方式编写相同的代码Dispatcher.Invoke()
  • 能够取消调用的正在运行的任务 doSomething()
  • 能够链接多个调用,即等待doSomething()并在它完成后,doAnotherThing()使用上一次调用的结果

因此,为什么我想使用异步模型来编写它。

我该怎么办?

AAA*_*ddd 5

正如您所标记的方法asyncawaitTask.Run这样延续上运行的UI,也只剩下长时间运行在它(貌似CPU绑定的)工作

private async void btnAction_Click(object sender, RoutedEventArgs e)
{
   btnAction.IsEnabled = false;
   txtResult.Text = "";       
   lblStatus.Text = "Wait...";

   string input = query.Text;

   // calling a method that takes a long time (>3s) to finish and return
   var attempt =  await Task.Run(() => someLibrary.doSomethingWith(input));

   if (attempt.ContainsKey("success"))
   {
      if (attempt["success"] == true)
      {
         txtResult.Text = "Success! The door is: " + (attempt["is_open"] ? "open" : "closed");
         lblStatus.Text = "";
      }
      else
      {
         lblStatus.Text = "Error! The service says: " + attempt["errorMessage"];
      }
   }  
   else
   {
      MessageBox.Show("There was a problem getting results from web service.");
      lblStatus.Text = "";
   }

   btnAction.IsEnabled = true;

}
Run Code Online (Sandbox Code Playgroud)

更新

要取消任务,您将使用CancellationTokenfrom am 实例CancellationTokenSource并将其传递给Task.Run您的长时间运行的方法来检查IsCancellationRequested(如果可以的话)。你打电话取消CancellationTokenSource.Cancel

请注意,您可能希望将其包装在try catch finally 中OperationCanceledException然后将您的按钮启用代码放在 finally 中