实现是否会改变等待的行为?(Does implementation change the behaviour of await?)

编程入门 行业动态 更新时间:2024-10-18 10:27:08
实现是否会改变等待的行为?(Does implementation change the behaviour of await?)

Await关键字与等待类型一起使用(.NET附带现有的两种类型, Task和Task<T> )。 但是,可以编写自己的等待类型。

msdn博客文章指出:

你可以想到以下代码:

await FooAsync(); RestOfMethod();

与此类似:

var t = FooAsync(); var currentContext = SynchronizationContext.Current; t.ContinueWith(delegate { if (currentContext == null) RestOfMethod(); else currentContext.Post(delegate { RestOfMethod(); }, null); }, TaskScheduler.Current);

上面的(伪)代码是否遵循awaitable类型的实现(例如Task ),或者它可能只是编译器处理await关键字右侧的任何等待类型的方式?

在下面的评论部分,有一篇文章解释了TaskScheduler和SynchronizationContext之间的区别。

主要区别在于SynchronizationContext是使用委托的一般机制,而TaskScheduler特定于并且适用于任务(您可以使用TaskScheduler.FromCurrentSynchronizationContext获取包装SynchronizationContext的TaskScheduler)。 这就是为什么等待任务考虑到两者,首先检查SynchronizationContext(作为大多数UI框架支持的更一般的机制),然后回退到TaskScheduler。 等待不同类型的对象可能会选择首先使用SynchronizationContext,然后再回退到特定于该特定类型的其他某种机制。

如果我正确理解了最后一句,这意味着我可以在continueWith方法中放置我想要的任何委托(我的意思是上面代码示例中的t.ContinueWith调用),即修改await在与我的自定义等待对象一起使用时的工作方式。

万一你想了解更多: http : //blogs.msdn.com/b/pfxteam/archive/2009/09/22/9898090.aspx

Await keyword is used with awaitable types (.NET comes with existing two such types, Task and Task<T>). However, it's possible to write your own awaitable type.

The msdn blog post states that:

you can think of the following code:

await FooAsync(); RestOfMethod();

as being similar in nature to this:

var t = FooAsync(); var currentContext = SynchronizationContext.Current; t.ContinueWith(delegate { if (currentContext == null) RestOfMethod(); else currentContext.Post(delegate { RestOfMethod(); }, null); }, TaskScheduler.Current);

Does the (pseudo)code above follow from the implementation of awaitable type (such as Task), or maybe is it just the way the compiler deals with any awaitable type that is on the right of the await keyword?

In the comments section below, there's a post explaining the difference between TaskScheduler and SynchronizationContext.

The primary difference is that SynchronizationContext is a general mechanism for working with delegates, whereas TaskScheduler is specific to and catered to Tasks (you can get a TaskScheduler that wraps a SynchronizationContext using TaskScheduler.FromCurrentSynchronizationContext). This is why awaiting Tasks takes both into account, first checking a SynchronizationContext (as the more general mechanism that most UI frameworks support), and then falling back to a TaskScheduler. Awaiting a different kind of object might choose to first use a SynchronizationContext, and then fall back to some other mechanism specific to that particular type.

If I understand the last sentence correctly, it means I can put any delegate I want in the continueWith method (I mean the t.ContinueWith call in code sample above), i.e. modify how await works when used with my custom awaitable object.

Just in case you want to know more: http://blogs.msdn.com/b/pfxteam/archive/2009/09/22/9898090.aspx

最满意答案

上面的(伪)代码是否遵循awaitable类型的实现(例如Task),或者它可能只是编译器处理await关键字右侧的任何等待类型的方式?

代码确实遵循任务的实现。 但它的存在只是为了帮助你理解它是如何工作的,因为它类似于延续。

编译器生成的实际代码差别很大, 并且不考虑实际的等待类型 。 它所做的就是寻找一个GetAwaiter方法,该方法返回一个具有IsCompleted , GetResult , OnCompleted的awaiter。 等待实现的是既可以捕获SynchronizationContext.Current也可以不捕获(或完全做其他事情)。

你可以在这里看到实际的代码。

即完全修改await与我的自定义等待对象一起使用时的工作方式。

只要对你有意义,你就可以做任何你喜欢的事。 您甚至可以使用扩展方法制作内置类型。 例如这段代码:

public static Awaiter GetAwaiter(this string s) { throw new NotImplementedException(); } public abstract class Awaiter : INotifyCompletion { public abstract bool IsCompleted { get; } public abstract void GetResult(); public abstract void OnCompleted(Action continuation); }

将使您能够编译await "bar"; 。 它当然会在运行时失败,但编译器不知道这一点。

Does the (pseudo)code above follow from the implementation of awaitable type (such as Task), or maybe is it just the way the compiler deals with any awaitable type that is on the right of the await keyword?

The pseudo code does follow from the implementation of tasks specifically. But it exists only to help you understand how it works because it's similar to continuations.

The actual code the compiler generates is widely different and it doesn't take the actual awaitable type into consideration. All it does is look for a GetAwaiter method that returns an awaiter that has IsCompleted, GetResult, OnCompleted. The awaitable implementation is the one that either captures SynchronizationContext.Current or not (or does something else entirely).

You can see the actual code here.

i.e. completely modify how await works when used with my custom awaitable object.

You can do whatever you like as long as it makes sense to you. You can even make built-in types awaitable with an extension method. For example this code:

public static Awaiter GetAwaiter(this string s) { throw new NotImplementedException(); } public abstract class Awaiter : INotifyCompletion { public abstract bool IsCompleted { get; } public abstract void GetResult(); public abstract void OnCompleted(Action continuation); }

Will enable you to compile await "bar";. It will fail on runtime of course, but the compiler doesn't know that.

更多推荐

本文发布于:2023-08-07 06:13:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1463078.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:是否会   implementation   change   behaviour   await

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!