C# 什么时候应该使用Task.Run()?
这两种方法的区别是什么:C# 什么时候应该使用Task.Run()?,c#,asynchronous,concurrency,task,C#,Asynchronous,Concurrency,Task,这两种方法的区别是什么: public static int Main(string[] args) { string result; Task.Run(async () => { Task<string> getStringTask = GetStringAsync(); result = await validationsTask; }).Wait(); Console.WriteLine(re
public static int Main(string[] args)
{
string result;
Task.Run(async () =>
{
Task<string> getStringTask = GetStringAsync();
result = await validationsTask;
}).Wait();
Console.WriteLine(result);
}
publicstaticintmain(字符串[]args)
{
字符串结果;
Task.Run(异步()=>
{
任务getStringTask=GetStringAsync();
结果=等待验证任务;
}).Wait();
控制台写入线(结果);
}
及
publicstaticintmain(字符串[]args)
{
任务getStringTask=GetStringAsync();
getStringTask.Wait();
string result=getStringTask.result;
控制台写入线(结果);
}
我见过很多人使用第一种方法,我不知道为什么。有什么特别的优势吗?建议哪种方法用于在控制台应用程序的main中等待异步方法?第一种方法使用线程池线程在异步函数完成后继续执行,而第二种方法使用启动异步函数的调用线程继续执行 第二种方法可能会出现死锁。例如(类似于从书中摘录的示例:
publicstaticintmain(字符串[]args)
{
任务getStringTask=GetStringAsync();
string result=getStringTask.result;//主线程在等待时被阻塞。
控制台写入线(结果);
}
公共任务GetStringAsync()
{
//发出HTTP请求并让线程从GetHttp返回
HttpResponseMessage msg=等待新的HttpClient()。GetAsync(“http://Wintellect.com/");
//我们从未到达这里:主线程正在等待这个方法完成,但是这个方法
//无法完成,因为主线程正在等待它完成-->死锁!
返回wait 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);
}
publicstaticintmain(字符串[]args)
{
字符串结果;
Task.Run(异步()=>
{
//我们在线程池线程上运行
任务getStringTask=GetStringAsync();
//我们之所以到这里,是因为任何线程池线程都可以执行此代码,我们不需要主线程。
结果=等待验证任务;
}).Wait();
控制台写入线(结果);
}
另一个解决方案是使用(false),摘自本书:
将true传递给此方法会产生与不调用相同的行为
方法。但是,如果传递false,则等待运算符会传递
不查询调用线程的SynchronizationContext对象,以及
线程池线程完成任务,它只是简单地完成它和
等待操作符通过线程池线程执行后的代码
公共任务GetStringAsync()
{
HttpResponseMessage msg=等待新的HttpClient()。GetAsync(“http://Wintellect.com/“”。配置等待(错误);
//我们现在来到这里是因为线程池可以执行此代码
//而不是强制主线程执行它。
返回await msg.Content.ReadAsStringAsync().ConfigureAwait(false);
}
有什么特别的优势吗
通常使用async
方法,操作是同步初始化的,然后等待可以与wait
异步,也可以与wait()
同步。Main
方法不能是async
所以你必须在那里用wait()
阻塞,或者你可以做Console.ReadKey()
运行,直到用户按键
Task.Run(async()=>…)
在初始化async
操作的成本很高的情况下非常有用。这样,在初始化操作时,允许主线程继续
建议在控制台应用程序的main中等待异步方法使用哪种方法
我将使用第二种方法的稍微修改版本。您可以添加一个mainascync
方法并从Main
调用它,然后您可以在其中使用wait
public static async Task MainAsync()
{
string result = await GetStringAsync();
Console.WriteLine(result);
}
public static int Main(string[] args)
{
MainAsync().Wait();
}
此外,对于控制台应用程序,也没有死锁风险,因为没有SynchronizationContext
,并且使用默认的线程池
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);
}
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);
}
public static async Task MainAsync()
{
string result = await GetStringAsync();
Console.WriteLine(result);
}
public static int Main(string[] args)
{
MainAsync().Wait();
}