控制不在非异步块中的Task.Result之后产生

时间:2015-06-24 05:13:13

标签: c# asynchronous async-await task-parallel-library task

我正在尝试使用MSDN示例。我遇到了以下问题。从具有async模式的按钮单击事件处理程序运行async代码块时,它可以正常工作(button1_Click)。但是对于button2_Click,控件不会超过TaskObj.Result。可能是什么原因?

  private async void button1_Click(object sender, EventArgs e)//this works fine
    {
        Task<int> TaskObj = AccessTheWebAsync();
        string a ="I came here..";

        int y = await TaskObj;

        string a1 = "I came here also..";
    }

    private  void button2_Click(object sender, EventArgs e)//this is not working
    {
        Task<int> TaskObj = AccessTheWebAsync();
        string a = "I came here..";//control yielded here
        int y = TaskObj.Result;//something happened here
        string a1 = "Why I couldn't come here?";//why control is not reaching here?
    }


    async Task<int> AccessTheWebAsync()
    { 
        HttpClient client = new HttpClient();
        Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");        
        DoIndependentWork();
        string urlContents = await getStringTask;
        return urlContents.Length;
    }

    private void DoIndependentWork()
    {
      IList<Int32>intK = Enumerable.Range(1, 100000000).ToList();
      foreach (int x in intK)
      {
          int y = x * 2;
      }
    }

1 个答案:

答案 0 :(得分:4)

  

可能是什么原因?

差异是一个死锁,而另一个不是。当您await时,您通过将控制权交还给调用方法来异步等待。使用Task.Result时,您会同步阻止呼叫。这导致僵局。

为什么呢?因为有一种称为&#34;同步上下文&#34;这里涉及到,它负责在之前使用的相同上下文中执行延续(第一个await之后的所有代码)的一些魔力,在您的情况下是 UI线程。因为你与Task.Result同步阻塞,所以延续无法将自己编组回UI线程,因为它正在.Result等待它自己。

相反,请使用await与之前的按钮点击一样:

private async void button2_Click(object sender, EventArgs e)//this is not working
{
    Task<int> TaskObj = AccessTheWebAsync();
    string a = "I came here..";//control yielded here
    int y = await TaskObj;
}