C# 异步/等待执行步骤

C# 异步/等待执行步骤,c#,C#,谁能给我解释一下为什么second工作在完成后显示 Stating Doing Work Working! Done Working! Work completed 第二个问题为什么我不能像下面这样得到任务结果: Task result = await LongOperation(); 最后一个问题是,在我的代码中使用Task.Run代表wait/async的原因是什么?在哪里可以使用它,或者使用它不好 class Program { static void Main(string[

谁能给我解释一下为什么second
工作
完成后显示

Stating
Doing Work
Working!
Done
Working!
Work completed
第二个问题为什么我不能像下面这样得到任务结果:

Task result = await LongOperation();
最后一个问题是,在我的代码中使用
Task.Run
代表wait/async的原因是什么?在哪里可以使用它,或者使用它不好

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Starting");
        var worker = new Worker();
        worker.DoWork();
        Console.WriteLine("Done");
        Console.ReadKey();
    }
}

public class Worker
{
    public async void DoWork()
    {
        Console.WriteLine("Doing work");

        await LongOperation();
        await LongOperation();

        Console.WriteLine("Work completed");
    }

    private async Task LongOperation()
    {
        Console.WriteLine("Working!");
        await Task.Delay(200);
    }
}

这是因为您声明了
DoWork()
异步,返回类型为
void
。这使得它成为一个异步运行的“触发并忘记”方法。如果您有
DoWork()
返回一个
任务而不是
void
,您可以
等待它,这将确保在
DoWork()
完成执行后出现“完成”消息

此外,
await
将打开任务结果,因此您不能等待它并同时获取值。如果您希望直接使用
任务
结果,请不要等待它

代码中没有指定您应该在哪里使用任务的特定区域。Run()

出现“Done!”的原因比您预期的要早,因为您没有在
worker.DoWork()前面等待
(并且
DoWork
需要返回
任务
,才能使用
等待
)。因此,所发生的是
DoWork()
立即返回,执行延迟到另一个线程,并立即转到下一行,即控制台写入“done”

关于
任务结果=等待长时间操作()
等待
作为参数等待对象(即
任务
),代表您检查其
。结果
属性,提取结果并返回。因此,您要么删除
wait
以获取任务实例,要么放入
wait
以等待任务完成并提取调用的实际返回值

使用
任务有几个原因。运行
或通过任务工厂,一个例子是传递lambda函数以执行(可能带有闭包)。我会参考第三方物流上的MSDN库了解详细信息

  • 工作
    完成后显示因为在您的
    静态void Main
    中,您没有等待
    worker.DoWork()完成,因此程序执行下一行。您应该像这样更改
    DoWork
    方法:

    public async Task DoWork()
    {
        //
    }
    
    worker.DoWork().GetAwaiter().GetResult();
    
  • 然后按如下方式更改对它的调用:

    public async Task DoWork()
    {
        //
    }
    
    worker.DoWork().GetAwaiter().GetResult();
    
  • 您不能这样做,因为使用
    wait
    您的
    long操作将不会返回
    任务
    。例如,如果您有这样的签名,当您使用
    wait
    时,您将打开结果:

    public Task<int> GiveANumberAsync()
    {
        return Task.FromResult(12);
    }
    
    int result = await GiveANumberAsync();
    
    public任务GiveANumberAsync()
    {
    返回任务.FromResult(12);
    }
    int result=wait GiveANumberAsync();
    
  • 对于这个问题,我想我无法比斯蒂芬更好地解释,他说:

  • 使用Task.Run调用CPU绑定的方法


    逐一回答您的问题:

  • Main
    中,您不需要等待
    DoWork
    。这意味着调用它,然后继续执行
    Main
    中的代码,而无需等待
    DoWork
    完成。因此,在第二次“工作”之前,立即将“完成”打印到控制台
  • 这不是
    await
    关键字所做的。从:
  • 等待运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成。这项任务是正在进行的工作。[...] 应用wait运算符的任务通常是对实现基于任务的异步模式的方法的调用的返回值。示例包括
    Task
    Task
    类型的值

    实际上,为了等待一个方法,它必须具有返回类型
    Task
    ,其中T是代码中返回的实际类型。在本例中,您的方法
    LongOperation
    实际上不会返回任何内容

  • Task.Run
    用于将任何方法或代码块作为任务运行。它可以被触发和遗忘(
    Task.Run([something];
    ),也可以像任何其他任务一样等待(
    wait Task.Run([something]);
    。请参阅相关文档,尽管我不确定它会有多大帮助。用户对此进行了很好的解释,并提供了一些其他相关信息

  • 1.因为您调用了两次
    LongOperation
    。2.因为这不是
    await
    的工作方式。3.异步调用同步操作。(以后,请尽量在每篇帖子中只回答一个问题。)请看。你应该避免在同一个线程中问多个问题。此外,如果你提供一些关于你所问问题的上下文(特别是在第一个问题中),这将使我们更容易理解表示。您不能等待无效返回类型。请尝试避免无效语法。不控制任务激发和forgetCPU绑定方法是最常用的使用方法