C#中的Async/await vs Task.Run

Rau*_*wal 5 .net c# multithreading asynchronous

我刚接触这个异步的东西.
请忍受我缺乏的知识.

  1. 据说当一个方法遇到等待时......" 它告诉等待它在完成时运行方法的其余部分,然后从异步方法返回. "
    我没有得到这个部分.
    那么这是否意味着该方法仍然保持同步运行并等待直到等待返回,然后继续该方法的其余部分?
    如果没有请解释那么为什么Task.Run需要在后台运行方法或以火灾和忘记方式运行.我仍然可以通过等待来实现吗?即
    该方法继续执行其余的语句,而不等待await返回.
    我希望这与后台运行方法类似.或者不是吗?我很迷惑.

  2. 如果一个方法用async和await标记,然后又在一个单独的层中异步调用另一个方法,该层也标记为async和await ..
    那么第一个用async和await标记的方法的调用是如何调用的名称ABC应该是什么样的?
    我不想将该方法注释为async/await.所以

    Task.Run(() => DoWork());
    
    Run Code Online (Sandbox Code Playgroud)

    来自ABC()没有标记为async/await?
    还是它违背了异步原则?

这是我想要实现的......

   public IList<CreateCaseOutput> ABC(CreateCaseInput CreateCaseInput,SaveCaseSearchInput SaveCaseSearchInput)
    {
        CaseSQL.getABCParameters(CreateCaseInput, RequestType, out strSPQuery, out listParam);
        var AcctLst = rep.ExecuteStoredProcedure<CreateCaseOutput>(strSPQuery, listParam).ToList();

        if (!string.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString()))
        {
            Task.Run(async () =>
            {
                await DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
            }).ConfigureAwait(false);              
        }
        console.writeLine("After Async called");
        return AcctLst;
    }

    public async Task<SaveCaseSearchOutput>> DEF(SaveCaseSearchInput SaveCaseSearchInput,Int64? case_key)
    {

            CaseSQL.getDEFParameters(SaveCaseSearchInput, case_key, out strSPQuery, out listParam);
            var AcctLst = await rep.ExecuteStoredProcedureAsync<SaveCaseSearchOutput>(strSPQuery, listParam);
            return AcctLst;
    }
Run Code Online (Sandbox Code Playgroud)

异步/等待的DEF需要在后台调用并且忘记来自ABC的方法并且一旦被解雇我想继续使用ABC的其余部分并在后台运行DEF.这种火灾和忘记方法有什么问题?如果我打电话

只要

DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq); 
Run Code Online (Sandbox Code Playgroud)

代替

 Task.Run(async () =>
                {
                    await DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
                }).ConfigureAwait(false);              
            }
            return AcctLst;
Run Code Online (Sandbox Code Playgroud)

那么这段代码在调试器中同步运行.

难道我做错了什么 ?

Ste*_*ary 8

那么这是否意味着该方法仍然保持同步运行并等待直到等待返回,然后继续该方法的其余部分?

不,等待有一个"回调"机制.因此,该方法只是将其自身注册为等待.当等待完成时,它将执行其回调,其中包括async方法的继续.

在此期间,该async方法返回不完整的任务.

如果没有请解释为什么需要Task.Run来在后台运行方法或以火灾和遗忘的方式.

如果要在后台线程上运行,请使用Task.Run.Task.Run只是安排工作到线程池.

我仍然可以通过等待来实现吗?即该方法继续执行其余的语句,而不等待await返回.我希望这与后台运行方法类似.或者不是吗?我很迷惑.

好吧,你可以通过等待它来"忘记"任务:

MyMethod()
{
  SomeMethodAsync(); // Note: no await; we just ignore the task.
}
Run Code Online (Sandbox Code Playgroud)

但是,你几乎从不想做 "开火而忘记".很容易> 90%的人都会要求它,这实际上是一个设计错误.

我不想将该方法注释为async/await ......或者它是否违反了异步原则?

这违背了原则.如果你考虑一下,阻塞异步代码并没有多大意义.你想要解决使方法异步(意味着它不阻塞线程),然后阻塞它的线程的麻烦?为什么呢?有时在实践中,代码将在转换到异步代码期间暂时以这种状态结束,但这是一个棘手的地方.

有关更多信息,请参阅有关异步最佳实践的文章,尤其是"始终异步".

  • 你不应该在 ASP.NET 上使用 `Task.Run`。如果你完全使用 `async`,那么一直使用它直到控制器。这就是它应该的样子。如果客户端想要在请求进行时做其他工作,那么*客户端*可以使用异步编程。 (2认同)