这两种方法之间的区别是什么:
public static int Main(string[] args)
{
string result;
Task.Run(async () =>
{
Task<string> getStringTask = GetStringAsync();
result = await validationsTask;
}).Wait();
Console.WriteLine(result);
}
和
public static int Main(string[] args)
{
Task<string> getStringTask = GetStringAsync();
getStringTask.Wait();
string result = getStringTask.Result;
Console.WriteLine(result);
}
我见过很多人使用第一种方法,我不知道为什么。有什么特别的优势吗?建议哪一个在控制台应用程序的主要内部等待异步方法?
答案 0 :(得分:2)
有什么特别的优势吗?
通常使用async
方法同步初始化操作,然后等待可以与await
异步或与Wait()
同步。 Main
方法不能为async
,因此您可以强行阻止Wait()
,或者您可以执行Console.ReadKey()
直到用户按下某个键。
Task.Run(async () => ... )
操作初始化成本高时, async
非常有用。这样就可以在操作初始化时允许主线程继续。
建议哪一个在控制台应用程序的主要内部等待异步方法?
我会使用第二种方法的略微修改版本。您可以添加MainAsync
方法并从Main
调用该方法,然后您可以在其中使用await
。
public static async Task MainAsync()
{
string result = await GetStringAsync();
Console.WriteLine(result);
}
public static int Main(string[] args)
{
MainAsync().Wait();
}
同样使用控制台应用程序,没有死锁的风险,因为没有SynchronizationContext
并且使用了默认的线程池。
答案 1 :(得分:0)
第一种方法在使用线程池线程完成asynch函数后继续执行,而第二种方法使用启动asynch函数的调用线程继续执行。
使用第二种方法,可能会出现死锁。例如(类似于从书籍CLR via C#)中提取的示例:
) public static int Main(string[] args)
{
Task<string> getStringTask = GetStringAsync();
string result = getStringTask.Result; //the main thread is blocked waiting.
Console.WriteLine(result);
}
public Task<string> GetStringAsync()
{
// Issue the HTTP request and let the thread return from GetHttp
HttpResponseMessage msg = await new HttpClient().GetAsync("http://Wintellect.com/");
// We never get here: The main thread is waiting for this method to finish but this method
// can't finish because the main thread is waiting for it to finish --> DEADLOCK!
return await msg.Content.ReadAsStringAsync();
}
所以第一种方法避免了这个问题:
public static int Main(string[] args)
{
string result;
Task.Run(async () =>
{
// We run on a thread pool thread
Task<string> getStringTask = GetStringAsync();
// We do get here because any thread pool thread can execute this code, we don't need the main thread.
result = await validationsTask;
}).Wait();
Console.WriteLine(result);
}
另一个解决方案是使用从书中提取的ConfigureAwait(false):
将true传递给此方法会给您与不调用相同的行为 这个方法。但是,如果传递false,则await运算符会执行 不查询调用线程的SynchronizationContext对象,以及何时 线程池线程完成theTask,它只是完成它和 await运算符通过线程池线程执行后的代码。
public Task<string> GetStringAsync()
{
HttpResponseMessage msg = await new HttpClient().GetAsync("http://Wintellect.com/").ConfigureAwait(false);
// We DO get here now because a thread pool can execute this code
// as opposed to forcing the main thread to execute it.
return await msg.Content.ReadAsStringAsync().ConfigureAwait(false);
}