Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
432 views
in Technique[技术] by (71.8m points)

c# - 过度使用异步等待? [重复](Excessive use of async await? [duplicate])

I'm wondering if I use async and await to excessively in my code and if there are (performance) penalties in doing so?

(我想知道我是否在代码中过度使用了asyncawaitawait (性能)方面的惩罚?)

What I often do:

(我经常做什么:)

static void Main()
{
    var result = Task<int>.Run (()=> S1Async(1)).Result;
    Console.WriteLine(result);
}

static async Task<int> WrapperAsync(Func<int, Task<int>> func) => await func(2);
static async Task<int> S1Async(int x) => await WrapperAsync(async t=> await S2Async(x * t));
static async Task<int> S2Async(int x) => await WrapperAsync(async t=> await S3Async(x * t));
static async Task<int> S3Async(int x) => await WrapperAsync(async t=> await S4Async(x * t));
static async Task<int> S4Async(int x) => await Task.FromResult(x * 10);

I think the async-awaits can be skipped and that this code is similar:

(我认为可以跳过异步唤醒,并且此代码类似:)

static void Main()
{
    var result = Task<int>.Run(() => S1Async(1)).Result;
    Console.WriteLine(result);
}

static Task<int> WrapperAsync(Func<int, Task<int>> func) => func(2);
static Task<int> S1Async(int x) => WrapperAsync(t => S2Async(x * t));
static Task<int> S2Async(int x) => WrapperAsync(t => S3Async(x * t));
static Task<int> S3Async(int x) => WrapperAsync(t => S4Async(x * t));
static Task<int> S4Async(int x) => Task.FromResult(x * 10);

When tasks are nested with just one task per level, is it safe to skip async/await?

(当任务只嵌套一个级别的每个任务时,跳过异步/等待是否安全?)

Both code-samples gives the same result in LinqPad, so I assume they are similiar, but maybe there are side-effects I should be aware of?

(这两个代码样本在LinqPad中给出的结果相同,因此我认为它们是相似的,但也许还有一些我应该注意的副作用?)

  ask by Frode translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Short answer is: yes, you can skip them in this case and yes, there's a performance penalty.

(简短的答案是:是的,在这种情况下可以跳过它们,是的,这会降低性能。)

When all your method does is await once and immediately return, like this:

(当您的所有方法都await一次并立即返回时,如下所示:)

async Task FooAsync()
{
    /* ... */

    await BarAsync();
}

then it would be pretty much equivalent to write:

(那么写起来就差不多了:)

Task FooAsync()
{
    /* ... */

    return BarAsync();
}

The meaning of async is (from the perspective of FooAsync ): okay, the operation BarAsync might take a while to complete, so if we get an uncompleted Task from it let me save my current state and return the control flow up to my caller.

(async的含义是(从FooAsync的角度来看):好的, BarAsync操作可能需要一段时间才能完成,因此,如果我们从中获取未完成的Task ,请让我保存当前状态并将控制流返回给调用者。)

Once the Task gets completed, I want to pick up the state and continue what I've been doing.

(Task完成后,我想获取状态并继续执行我一直在做的事情。)

In this case it's clear that there is no additional work that would be performed after the BarAsync Task completes, so you can just return that Task to the caller, since effectively FooAsync completes the exact same moment that Task would.

(在这种情况下,很明显,在BarAsync Task完成之后,没有其他工作可以执行,因此您可以将Task返回给调用者,因为FooAsyncTask完全相同。)

There's no need to save any state or to schedule continuations.

(无需保存任何状态或安排继续。)

The overhead for this is not huge when we're talking about a single call, but if you call this method many times you might feel an impact.

(当我们谈论单个调用时,此操作的开销并不大,但如果多次调用此方法,则可能会产生影响。)

The compiler has to set up the entire async infrastructure the moment you declare your method to be async - the state machine, continuation scheduling, the whole package.

(编译器必须建立整个async架构,你宣布你的方法的时刻是async -状态机,延续调度,全包。)

So as a general rule: if you can simplify your method to not be async but simply return another Task , it's worth to do so.

(因此,作为一般规则:如果您可以简化方法以使其不async而仅返回另一个Task ,则值得这样做。)

As a side note: you certainly don't need to wrap your S1Async call into a Task.Run and you don't have to synchronously block in your Main since C# 7.1.

(附带一提:您当然不需要将S1Async调用包装到Task.Run并且从C#7.1开始就不必同步阻塞Main 。)

You can just write:

(您可以这样写:)

static async Task Main()
{
    var result = await S1Async(1);
    Console.WriteLine(result);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...