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();
}