jon*_*ith 3 .net c# async-await
考虑以下代码:
public async Task SomeMethodAsync(){
//1. code here executes on the original context
//for simplicity sake, this doesn't complete instantly
var result1 = await Method1Async().ConfigureAwait(false);
//2. code here doesn't executes in the original context
Run Code Online (Sandbox Code Playgroud)
现在我的问题是,如果在上面的方法中有另一个异步方法调用:
//again for simplicity sake, this doesn't complete instantly
var result2 = await Method2();
//3. code in question is here
}
Run Code Online (Sandbox Code Playgroud)
有问题的代码是在原始上下文中运行还是在另一个上下文中运行(可能是来自线程池或其他上下文的线程)?
此外,如果使用ConfigureAwait(false)调用method2,那么相关代码是否会在与段号2相同的上下文中运行?
//for simplicity sake, this doesn't complete instantly
var result1 = await Method1Async().ConfigureAwait(false);
//again for simplicity sake, this doesn't complete instantly
var result2 = await Method2();
//code in question is here
Run Code Online (Sandbox Code Playgroud)
假设你的异步方法没有立即完成,这里有两个简短的答案.
有问题的代码是在原始上下文中运行还是在另一个上下文中运行(可能是来自线程池或其他上下文的线程)?
有问题的代码将具有空SynchronizationContext.Current值,因此将以默认值运行SynchronizationContext.
关于有问题的代码运行的线程:SynchronizationContext做出决定.代码被发布/发送到a SynchronizationContext,后者又将操作转发到特定的计算资源,例如特定的线程,特定的CPU核心或其他东西.在默认情况下SynchronizationContext,线程的选择取决于托管应用程序的内容(例如,控制台应用程序与ASP.NET应用程序).在非默认情况下SynchronizationContext,计算资源的选择取决于实现者的心血来潮:它可以在网络共享上运行.
此外,如果使用ConfigureAwait(false)调用method2,那么相关代码是否会在与段号2相同的上下文中运行?
如果method2有ConfigureAwait(false),那么有问题的代码也将在默认情况下运行SynchronizationContext.换句话说,当我们使用时false,任务不再尝试在捕获的上下文中继续.
这是一个实验(完整列表在这里),可以回答你的两个问题.
该实验使用SynchronizationContext维护简单的a ,将其string State自身重置为当前上下文Post,并覆盖ToString()以输出其State值.
public class MySyncContext : SynchronizationContext
{
public string State { get; set; }
public override void Post(SendOrPostCallback callback, object state)
{
base.Post(s => {
SynchronizationContext.SetSynchronizationContext(this);
callback(s);
}, state);
}
public override string ToString() => State;
}
Run Code Online (Sandbox Code Playgroud)
它是什么让我们看到代码是否在原始上下文中运行.
那么,让我们回忆一下你问的问题:
有问题的代码是在原始上下文中运行还是在另一个上下文中运行(可能是来自线程池或其他上下文的线程)?
要回答这个问题,我们有一个接近您的设置的实验.它首先将原始文件设置SynchronizationContext为已知状态,然后等待两个异步方法,ConfigureAwait(false)首先使用,记录当前的当前SynchronizationContext状态.
static async Task Run()
{
var syncContext = new MySyncContext { State = "The Original Context" };
SynchronizationContext.SetSynchronizationContext(syncContext);
Console.WriteLine("Before:" + SynchronizationContext.Current);
await Task.Delay(1000).ConfigureAwait(false);
Console.WriteLine("After Result1:" + SynchronizationContext.Current);
await Task.Delay(1000);
Console.WriteLine("After Result2:" + SynchronizationContext.Current);
}
Run Code Online (Sandbox Code Playgroud)
您想知道在第二种方法之后运行的代码是否会在原始上下文中运行.输出答案.第一个和第二个异步方法都没有将它们的延续发布到原始上下文.
上面的代码ConfigureAwait(false)输出:
Before:The Original Context
After Result1:
After Result2:
Run Code Online (Sandbox Code Playgroud)
如果我们改变上面的代码ConfigureAwait(true),两个方法都在原始上下文中运行它们的连续,输出是这样的:
Before:The Original Context
After Result1:The Original Context
After Result2:The Original Context
Run Code Online (Sandbox Code Playgroud)
所以你有它.对于我来说,运行带有多种不同值的和的各种组合的完整代码列表以及延迟为0以查看会发生什么是很有启发性的.truefalseSynchronizationContext
还有值得阅读SynchronizationContext的部分内容吗?和它的所有有关的SynchronizationContext
| 归档时间: |
|
| 查看次数: |
776 次 |
| 最近记录: |