异步/等待与Task.Run在C#中 [英] Async/await vs Task.Run in C#

查看:67
本文介绍了异步/等待与Task.Run在C#中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于这个异步的世界,我还是一个新手.
请忍受我的知识不足.

I am just new to this world of asynchronous stuff.
Please bear with my lack of knowledge.

  1. 据说当一个方法遇到await时..."它告诉awaitable在完成后再运行该方法的其余部分,然后从async方法中返回."
    我没有得到这部分.
    那么这是否意味着该方法仍然保持同步运行,并一直等到可等待的返回,然后继续执行该方法的其余部分?
    如果不是,请说明原因,为什么需要 Task.Run 在后台或以一劳永逸的方式运行一种方法.我仍然可以通过 await 来实现,对吗?即
    该方法将继续执行其余语句,而无需等待等待返回.
    我希望这类似于后台运行方法.还是不是?我很困惑.

  1. It is said when a method encounters await ... "It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method."
    I did not get this part.
    So does it mean the method still keeps on running synchronously and waits till the awaitable returns and then proceeds with the rest of the method?
    If not please explain then why Task.Run is needed to run a method in the background or in a fire and forget manner. I could still be achieved via await also right? i.e.
    The method keeps on executing the rest of the statements without waiting for the await to return.
    I hope that is similar to a background run approach. Or is not it? I am confused.

如果某个方法被标记为async和await,而该方法又在另一个单独的层中异步调用了另一个方法,该层也被标记为async和await ..
那么第一个标有async并从另一个方法等待的方法的调用的名称ABC应该是什么样子?
我不想注释该方法为异步/等待.所以

If a method is marked with async and await and that in turn calls another method asynchronously in a separate layer that's also marked with async and await ..
then how the the call of the first method that's marked with async and await from a separate method say name ABC should look like?
I do not want to annotate that method to be async/await. So

Task.Run(() => DoWork());

来自ABC()的

是否可以不将其标记为异步/等待状态?
还是违反异步原则?

from ABC () is fine without marking it async/await?
Or is it against the principle of asynchrony?

这就是我要实现的目标...

Here is what I am trying to achieve ...

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

处于异步/等待状态的DEF需要在火灾中在后台调用,并忘记ABC的方法,一旦被触发,我想继续使用ABC的其余部分并在后台运行DEF.这种开火忘了"的方法有什么问题?如果我打电话

DEF which is async/await needs to be called in the background in fire and forget approach from ABC and once fired I want to continue with rest of ABC and run DEF in the background. What's wrong in this fire and forget approach ? If I call

DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq); 

代替

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

然后这段代码在调试器中同步运行.

then this code runs synchronously in debugger.

我做错什么了吗?

推荐答案

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

So does it mean the method still keeps on running synchronously and waits till the awaitable returns and then proceeds with the rest of the method?

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

No. The awaitable has a "callback" mechanism. So, the method just registers itself with the awaitable. When the awaitable completes, it will execute its callbacks, which include the continuation of the async method.

同时, async 方法返回不完整的任务.

In the meantime, the async method returns an incomplete task.

如果没有,请解释一下为什么需要Task.Run才能在后台或以一种开火"的方式运行方法.

If not please explain then why Task.Run is needed to run a method in the background or in a fire and forget manner.

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

If you want to run on a background thread, then use Task.Run. Task.Run just schedules work to the thread pool.

我仍然可以通过等待来实现,对吗?IE.该方法将继续执行其余的语句,而无需等待等待返回.我希望这类似于后台运行方法.还是不是?我很困惑.

I could still be achieved via await also right? i.e. The method keeps on executing the rest of the statements without waiting for the await to return. I hope that is similar to a background run approach. Or is not it? I am confused.

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

Well, you could "forget" the task by just not awaiting it:

MyMethod()
{
  SomeMethodAsync(); // Note: no await; we just ignore the task.
}

尽管如此,您几乎从未想要做开火而忘了".人们轻易地在90%以上的时间内提出要求,这实际上是设计错误.

You almost never want to do "fire and forget", though. Easily >90% of the time people ask for it, it's actually a design error.

我不想将该方法注释为异步/等待...还是违反异步原理?

I do not want to annotate that method to be async/await... Or is it against the principle of asynchrony?

这违反了原则.如果您考虑一下,阻塞异步代码实际上没有任何意义.您是否想让方法异步(即它不阻塞线程),然后在其上阻塞线程的麻烦?为什么呢?有时在实践中,在过渡到异步代码期间,代码会临时以这种状态结束,但这是一个棘手的地方.

That's against the principle. If you think about it, it doesn't really make sense to block on asynchronous code. You want to go through the trouble of making a method asynchronous (meaning it doesn't block a thread), and then block a thread on it? Why, exactly? Sometimes in practice, the code will temporarily end up in this kind of state during a transition to asynchronous code, but it's a tricky place to be.

有关更多信息,请参见我在异步最佳做法上的文章,特别是所有方式".

For more information, see my article on async best practices, particularly "async all the way".

这篇关于异步/等待与Task.Run在C#中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆