C# 实现是否会改变wait的行为?
C# 实现是否会改变wait的行为?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,Await关键字与可等待类型一起使用(.NET附带了现有的两种类型,Task和Task)。但是,您可以编写自己的等待类型 缔约国指出: 您可以考虑以下代码: await FooAsync(); RestOfMethod(); 与此性质类似: var t = FooAsync(); var currentContext = SynchronizationContext.Current; t.ContinueWith(delegate { if (currentContext == nul
Await
关键字与可等待类型一起使用(.NET附带了现有的两种类型,Task
和Task
)。但是,您可以编写自己的等待类型
缔约国指出:
您可以考虑以下代码:
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);
上面的(伪)代码是否遵循等待类型的实现(例如任务
),或者可能只是编译器处理关键字右侧的任何等待类型的方式
在下面的评论部分,有一篇文章解释了TaskScheduler和SynchronizationContext之间的区别
主要区别在于SynchronizationContext是一个通用的
用于处理委托的机制,而TaskScheduler是
特定于并迎合任务(您可以获得一个
使用包装SynchronizationContext
TaskScheduler.FromCurrentSynchronizationContext)。这就是为什么
等待任务首先检查
SynchronizationContext(作为大多数UI
框架支持),然后回到TaskScheduler。
等待不同类型的对象时可能会选择首先使用
SynchronizationContext,然后返回到其他机制
特定于该特定类型
如果我正确理解了最后一句话,这意味着我可以将我想要的任何委托放入continueWith
方法(我指的是上面的t.continueWith
调用代码示例),即修改await
与我的自定义等待对象一起使用时的工作方式
以防您想了解更多:
上面的(伪)代码是否遵循等待类型(如Task)的实现,或者可能只是编译器处理等待关键字右侧的任何等待类型的方式
伪代码确实遵循任务的具体实现。但它的存在只是为了帮助你理解它是如何工作的,因为它类似于延续
编译器生成的实际代码大不相同,而且它没有考虑实际的等待类型。它所做的只是寻找一个GetAwaiter
方法,该方法返回一个已IsCompleted
,GetResult
,OnCompleted
的等待器。等待的实现要么捕获SynchronizationContext.Current
要么不捕获(或者完全执行其他操作)
您可以看到实际的代码
i、 e.完全修改与我的自定义等待对象一起使用时等待的工作方式
只要对你有意义,你可以做任何你喜欢的事。您甚至可以使用扩展方法使内置类型成为可等待的。例如,此代码:
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);
}
将使您能够编译等待“bar”代码>。当然,它在运行时会失败,但编译器不知道这一点
上面的(伪)代码是否遵循等待类型(如Task)的实现,或者可能只是编译器处理等待关键字右侧的任何等待类型的方式
伪代码确实遵循任务的具体实现。但它的存在只是为了帮助你理解它是如何工作的,因为它类似于延续
编译器生成的实际代码大不相同,而且它没有考虑实际的等待类型。它所做的只是寻找一个GetAwaiter
方法,该方法返回一个已IsCompleted
,GetResult
,OnCompleted
的等待器。等待的实现要么捕获SynchronizationContext.Current
要么不捕获(或者完全执行其他操作)
您可以看到实际的代码
i、 e.完全修改与我的自定义等待对象一起使用时等待的工作方式
只要对你有意义,你可以做任何你喜欢的事。您甚至可以使用扩展方法使内置类型成为可等待的。例如,此代码:
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);
}
将使您能够编译等待“bar”代码>。当然,它在运行时会失败,但编译器不知道这一点。那么我不理解我引用的最后一句话的意思:“等待不同类型的对象[与任务不同,对吗?]可能会选择首先使用SynchronizationContext,然后退回到特定于该特定类型的其他机制。”@user4205580表示等待类型选择要执行的操作。编译器只是调用它。例如,当您调用task.ConfigureAwait(false)时
您将返回另一个名为ConfiguredTaskAwaitable
的等待任务,该任务根据传递给该方法的布尔值选择是否使用SynchronizationContext
。@user4205580因此await任务
将发布到SynchronizationContext
(如果有await任务)中task.ConfigureAwait(false)
不会。@user4205580这意味着等待任务
捕获了同步上下文的值。Current
是任务
的等待器实现的行为,不同的等待器可以有不同的行为。捕获当前同步上下文不是await
的语言功能。在这种情况下,t.ContinueWith(委托{if(currentContext==null)RestOfMethod();else currentContext.Post(委托{RestOfMethod();},null);
将不适用,因为它不会尝试在当前上下文上运行continuation(我指的是您的案例,t
是一个ConfiguredTaskAwaitable
)。因此引用的代码会随着waitable的实现而改变。然后我不理解最后一个sen是什么