异步任务如何阻止UI

时间:2015-12-15 08:55:19

标签: c# user-interface asynchronous async-await block

我有这段代码:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    Task<int> i = LongTaskAsync();    // first break point here
    int k = await i;
    print("Done, i=" + i);
}
private async Task<int> LongTaskAsync()
{
    await System.Threading.Tasks.Task.Delay(5 * 1000); // second break point here
    return 10;
}

调试时,我知道LongTaskAsync正在UI线程上运行。那么,为什么它不阻止UI以及如何阻止?

5 个答案:

答案 0 :(得分:1)

来自MSDN

的信息
  

该方法同步运行,直到它到达第一个await表达式,此时方法暂停,直到等待的任务完成。同时,控制返回到方法的调用者

答案 1 :(得分:0)

因为异步/等待构造是异步运行的 - 所以它不会阻止UI。在你的方法“int k = await i;”以异步方式运行。 “使用async修饰符指定方法,lambda表达式或匿名方法是异步的。该方法同步运行,直到它到达第一个await表达式,此时方法将暂停,直到等待的任务完成。同时,控制返回方法的调用者“。这就是为什么你的UI没有被阻止的原因。

答案 2 :(得分:0)

您的功能button_click被声明为异步。调用异步函数不会运行函数内部的代码。相反,代码被调度为由可用线程集合中的一个线程运行任务的请求,该线程称为线程池。

在计划任务之后,异步函数的调用将继续执行下一个语句,直到它到达语句以等待计划任务的结果。

每当线程池中的一个线程空闲时,它将检查是否安排了一段代码,如果是,它将运行代码。如果此线程调用另一个异步函数,则会安排任务等。

大多数异步功能都会在某个地方等待他们安排的任务的结果。因此,每个异步函数应返回任务或任务<TResult&gt;的规则。而不是虚空或TResult。

唯一的例外是事件处理程序:此方法可以返回async void,表示该任务将被调度,但调用者无法等待它。

此来电者是您的应用程序。应用程序安排一个任务来处理按钮单击事件,但在此事件结束之前不会等待。因此,您的申请将保持响应。

因为您的代码不会等到事件处理程序完成,所以事件程序可以再次调用事件处理程序。这通常会产生不良影响,您应该注意不要发生这种情况,例如通过禁用事件功能入口处的按钮并在事件结束时启用它。

答案 3 :(得分:-1)

当我尝试编写Android代码时,我遇到了同样的问题。后台任务与前台UI任务不同,它们独立运行。

AsyncTasks通常会使用前台中的线程来更新UI并执行与UI相关的任务

例如,

AsyncTask(params)-> {
@Override
   protected void onPreExecute() {
      super.onPreExecute();
     ..........
   }

   @Override
   protected String doInBackground(String... params) {
   ...............
   }

   @Override
   protected void onProgressUpdate(Integer... values) {
   ...............
   }

   @Override
   protected void onPostExecute(String result) {
   .................
   }
}

这里,每个任务都可以在自己的UI线程中处理,而不会干扰后台作业,当后台作业完成后,您可以更新UI。同时,您可以使用一些UI动画来保持UI忙碌。

答案 4 :(得分:-1)

您的示例不足以测试异步行为,我使用控制台应用程序测试了该行为。

static void Main(string[] args)
{
     string value1 = "First";
     Console.WriteLine(value1);

     GetSecondFromAsync();

     string value3 = "Third";
     Console.WriteLine(value3);

     string value4 = "Fourth";
     Console.WriteLine(value4);

     Console.ReadKey();
}

private static async void GetSecondFromAsync()
{
   await Task.Delay(3000);
   Console.WriteLine("Second");
}

来自MSDN的信息,

  

该方法同步运行,直到它到达第一个await   表达式,此时该方法暂停,直到等待   任务完成。同时,控制权返回给调用者   方法

在GetSecondFromAsync()中第一次等待时,只有这个方法被挂起,控件返回给调用者并执行剩下的。 所以输出就像

First
Third
Fourth
Second

这意味着Main中的线程未被阻止,它继续...