C# 任务的返回类型是否足以使方法异步运行?

C# 任务的返回类型是否足以使方法异步运行?,c#,asynchronous,async-await,task-parallel-library,C#,Asynchronous,Async Await,Task Parallel Library,我有一个简单的方法,它执行复杂的字符串操作并返回结果。如您所见,此方法的返回类型为Task。因此,我可以使用Task.FromResult(result)返回字符串的值 公共任务ComplexOperation() { 字符串结果=//执行一些复杂的操作 返回Task.FromResult(结果); } 然后,我可以使用wait关键字调用此方法 公共静态异步任务主(字符串[]args) { var myResult=await ComplexOperation(); } 因为我正在等待Com

我有一个简单的方法,它执行复杂的字符串操作并返回结果。如您所见,此方法的返回类型为
Task
。因此,我可以使用
Task.FromResult(result)
返回字符串的值

公共任务ComplexOperation()
{
字符串结果=//执行一些复杂的操作
返回Task.FromResult(结果);
}
然后,我可以使用
wait
关键字调用此方法

公共静态异步任务主(字符串[]args)
{
var myResult=await ComplexOperation();
}

因为我正在等待
CompelxOperation()
,(等待任务完成时返回)此方法是否会异步运行

根据您的评论,您需要执行以下操作:

public Task<string> ComplexOperation()
{
    return Task.Run(() =>  /* Do something complex */);
}
public static async Task Main()
{
    Console.WriteLine("Before" );
    var myResultTask = ComplexOperation();
    Console.WriteLine("After task creation");
    var result = await myResultTask;
    Console.WriteLine("After async await");
}

public Task<string> ComplexOperation()
{    
    Console.WriteLine("Creation");
    return Task.Run(() =>
    {
        Console.WriteLine("In before work");
        Thread.Sleep(500); //simulate work;
        Console.WriteLine("In after work");
        return "Done";
    });
}
公共任务ComplexOperation()
{
返回任务。运行(()=>/*做一些复杂的事情*/);
}
你可以这样玩:

public Task<string> ComplexOperation()
{
    return Task.Run(() =>  /* Do something complex */);
}
public static async Task Main()
{
    Console.WriteLine("Before" );
    var myResultTask = ComplexOperation();
    Console.WriteLine("After task creation");
    var result = await myResultTask;
    Console.WriteLine("After async await");
}

public Task<string> ComplexOperation()
{    
    Console.WriteLine("Creation");
    return Task.Run(() =>
    {
        Console.WriteLine("In before work");
        Thread.Sleep(500); //simulate work;
        Console.WriteLine("In after work");
        return "Done";
    });
}
公共静态异步任务Main() { 控制台。写入线(“之前”); var myResultTask=ComplexOperation(); Console.WriteLine(“任务创建后”); var结果=等待myResultTask; WriteLine(“异步等待后”); } 公共任务ComplexOperation() { Console.WriteLine(“创建”); 返回任务。运行(()=> { 控制台。写线(“在工作前”); Thread.Sleep(500);//模拟工作; 控制台。写线(“下班后”); 返回“完成”; }); }
并将该行为与仅返回
Task.FromResult
时切换到实现进行比较。同样,在这样的测试示例TBH中,它也没有太大意义。

正如您标记为async—获取异步方法的主方法—一样,您需要使用async关键字将该方法标记为asynchronous,并使结果成为一项任务

但在框架中,任务用于两个相关但不同的概念:并行化和异步编程

您正在做的是使用并行化

所以您只是在不同的线程上运行一些同步代码

基于您的示例,我认为您需要的是使用并行化,它可以通过使用多个线程并行工作来加速一些复杂的计算或工作

异步代码背后的概念是在等待外部资源(如web服务中的一些数据)时释放线程,以允许同时完成其他工作


因此,如果您需要使用本地资源执行复杂的工作,最好使用不带异步逻辑的任务,而使用远程资源时,您可以执行异步操作。

从语义上讲,ComplexOperation方法是异步的,因为它返回一个等待类型,为了遵循这一点,应该将其命名为ComplexOperationAsync

TAP中的异步方法包括返回可等待类型的方法的操作名称后的
Async
后缀,例如
Task
Task
ValueTask
、和
ValueTask

但它不是一种性能良好的异步方法。异步方法应立即返回不完整的
任务
,允许调用方
异步等待
任务而不被阻止。从:

基于TAP的异步方法可以在返回结果任务之前同步执行少量工作,例如验证参数和启动异步操作。同步工作应保持在最小值,以便异步方法可以快速返回

ComplexOperation
方法的作用正好相反:它强制调用线程执行复杂的操作,最后它返回一个已完成的任务。出于所有意图和目的,此操作根本不是异步的。它是100%同步和0%异步的,再加上一些开销(雪上加霜)。所以不要这样做,如果有某个库可以这样做,不要使用该库。这简直是坏习惯


澄清:因为术语异步方法在不同的上下文中可能意味着不同的事情,我应该澄清,这个答案的上下文是消费者的视角,消费者将方法的签名视为合同,并基于可见的契约而不是无形的实施建立期望。在这种情况下,方法
ComplexOperation
是异步的。如果我们切换视角并关注实现,那么方法
ComplexOperation
就不是异步的。我的声明“这只是一种不好的做法”指的是违反契约的做法,并为具有异步契约的方法提供同步实现。我不是在批评Task.FromResult方法本身的使用。我只是在批评它遵循一个复杂的/冗长的/潜在的操作时,根据方法的契约,它应该是异步的


另外,我感谢@DmytroMukalov(在中)提供了合同异步和实施异步之间的有益区别。

。您尝试过吗?;)@Franzgleichman是的,它很有效。只是不确定它是否实际异步运行。@MatthewTrip no它不会)导致
任务。FromResult
不是异步操作)@MatthewTrip错过了
//做一些复杂的事情
注释。是的,您将需要
TaskCompletionSource
并将您的工作卸载到另一个线程,这样它就不会阻止调用的线程。@MatthewTrip或只是
Task.Run(…)
将完成此工作。@Servy在我看来,使用
Task.Run
意味着创建状态机的不必要的开销,可以通过使用
Task.FromResult来避免(结果)
。如果我们结合使用
async
wait
Task.FromResult(result);
,那么代码就是异步的