2014-02-11 45 views
1

我想了解/了解更多关于异步/等待在C#中,我会把自己放在菜鸟类,所以你所有的意见/建议是值得欢迎的。我写了一个小测试,以更好地理解和澄清关于等待/异步。我的程序在“GetStringLength”调用后冻结了我试着读了几件事情,但看起来像被卡住了,我想到了我可能做错的专家意见。你能指导我或指着我正确的方向吗?等待异步澄清

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace AsyncPatterns 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Program p = new Program(); 
      Task<string> url = p.FindLargtestWebPage(new Uri[]{new Uri("http://www.google.com"), 
                  new Uri("http://www.facebook.com"), 
                  new Uri("http://www.bing.com") }); 
      Console.WriteLine(url.Result); 
      Console.ReadLine(); 
     } 

     public async Task<string> FindLargtestWebPage(Uri[] uris) 
     { 
      string highCountUrl = string.Empty; 
      int maxCount = 0; 

      foreach (Uri uri in uris) 
      { 
       Console.WriteLine(string.Format("Processing {0}", uri.ToString())); 
       var pageContent = await GetWebPageString(uri); 
       var count = await GetStringLength(pageContent); 
       if (count > maxCount) 
       { 
        highCountUrl = uri.ToString(); 
       } 
      } 
      return highCountUrl;    
     } 

     public async Task<int> GetStringLength(string pageData) 
     { 
      Console.WriteLine("Getting length"); 
      return await new Task<int>(() => 
      { 
       return pageData.Length; 
      }); 
     } 

     public async Task<string> GetWebPageString(Uri uri) 
     { 
      WebClient webClient = new WebClient(); 
      Console.WriteLine("Downloading string"); 
      return await webClient.DownloadStringTaskAsync(uri.ToString()); 
     } 

    } 
} 
+0

这是一个很好的视频,解释它是如何工作和它是什么http://www.youtube.com/watch?v=6_GTdR0gBVE –

+0

@DustinDavis:谢谢! –

回答

2

冻结罪魁祸首是这样的:

return await new Task<int>(() => 
{ 
    return pageData.Length; 
}); 

Task构造函数不启动任务,所以你要创建一个Task不运行。当你在awaitGetStringLength你将永远等待结果。

您可以手动启动任务:

var result = new Task<int>(() => 
{ 
    return pageData.Length; 
}); 

result.Start(); 

return result; 

或使用Task.Run静态方法,它会创建并启动任务:

return Task.Run(() => 
{ 
    return pageData.Length; 
}); 
+0

或者像斯蒂芬所说的那样只是有一个GetStringLength的同步版本。我没有看到在这里使用异步的理由,除非OP在实际代码中有其他逻辑。 –

+0

谢谢!欣赏它。感谢您指出为什么冻结的原因,同样的原因,我接受这个答案! –

+0

@KaiWang:OP明确表示他们正在尝试'async' /'await',所以我把这个问题看成是“我怎么才能得到这个工作”,而不是一个关于如何编写代码的问题。正如你所说,这应该不是真正的代码中的“异步”方法:) – porges

4

不要在async代码中使用Task构造,并且只有在您有异步工作时才使用asyncGetStringLength没有异步工作要做,所以它应该是:

public int GetStringLength(string pageData) 
{ 
    Console.WriteLine("Getting length"); 
    return pageData.Length; 
} 

欲了解更多信息,请参阅我的async/await intro

+0

谢谢!!感谢。 –