问题
I am trying to learn/understand more about async/await in C# and I would put myself in rookie category so all your comments/suggestions are welcome. I wrote small test to have better understanding and clarification about await/async. My program freezes after "GetStringLength" call I tried reading several things but looks like I am stuck and I thought of taking expert opinion on what I might be doing wrong. Can you please guide me or point me in right direction here?
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());
}
}
}
回答1:
The culprit for freezing is this:
return await new Task<int>(() =>
{
return pageData.Length;
});
This Task
constructor doesn't start the task, so you're creating a Task
that isn't running. When you await
on it in GetStringLength
you're going to be waiting forever for the result.
You can either start the task manually:
var result = new Task<int>(() =>
{
return pageData.Length;
});
result.Start();
return result;
or use the Task.Run
static method, which will create and start the task:
return Task.Run(() =>
{
return pageData.Length;
});
回答2:
Do not use the Task
constructor in async
code, and only use async
when you have asynchronous work to do. GetStringLength
has no asynchronous work to do, so it should be:
public int GetStringLength(string pageData)
{
Console.WriteLine("Getting length");
return pageData.Length;
}
For more information, see my async/await intro.
来源:https://stackoverflow.com/questions/21711548/await-async-clarification