为什么同步上下文无法等待? [英] Why sync context is not working for await?
问题描述
此答案说
默认情况下,await运算符将捕获当前的上下文",并将其用于恢复异步方法.
我正在控制台应用程序中尝试以下代码:
static void Main(string[] args)
{
Test().Wait();
}
private static async Task Test()
{
var context = new SynchronizationContext();
SynchronizationContext.SetSynchronizationContext(context);
Console.WriteLine("Thread before: " + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(await GetResultAsync());
Console.WriteLine("Thread after: " + Thread.CurrentThread.ManagedThreadId);
}
private static async Task<string> GetResultAsync()
{
return await Task.Factory.StartNew(() =>
{
Console.WriteLine("Thread inside: " + Thread.CurrentThread.ManagedThreadId);
return "Hello stackoverflow!";
});
}
...然后将其清除:
Thread before: 1
Thread inside: 3
Hello stackoverflow!
Thread after: 3
为什么?还有,如果我想在等待后使用同一线程,该如何设置同步上下文?
为什么?
new SynchronizationContext()
按照惯例与SynchronizationContext
. "no SyncCtx"和默认SyncCtx"都只是将工作排队到线程池中.
SynchronizationContext
与特定线程之间没有1:1的关系.例如:
- WinForms UI
SynchronizationContext
将使工作排队到单个UI线程. AFAIK,WinFormsSynchronizationContext
是一个单例,因此在这种情况下有一个1:1映射 . - WPF
SynchronizationContext
将把工作排队到其Dispatcher
.上一次我检查时,WPF将为每个顶级窗口创建一个新的 instance ,即使它们都使用相同的线程.这样就形成了N:1的映射. - 线程池(默认值/
null
)SynchronizationContext
可以将工作排队到任何线程池线程中.如果您不创建默认的SynchronizationContext
实例,则存在1:N映射.
还有,如果我想在等待后使用同一线程,该如何设置同步上下文?
您将需要使用自定义的SynchronizationContext
.我建议使用我的 AsyncContext
或AsyncContextThread
类型,因为这不是要编写的简单代码.>
This answer says
by default the await operator will capture the current "context" and use that to resume the async method.
I am trying this code in my console app:
static void Main(string[] args)
{
Test().Wait();
}
private static async Task Test()
{
var context = new SynchronizationContext();
SynchronizationContext.SetSynchronizationContext(context);
Console.WriteLine("Thread before: " + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(await GetResultAsync());
Console.WriteLine("Thread after: " + Thread.CurrentThread.ManagedThreadId);
}
private static async Task<string> GetResultAsync()
{
return await Task.Factory.StartNew(() =>
{
Console.WriteLine("Thread inside: " + Thread.CurrentThread.ManagedThreadId);
return "Hello stackoverflow!";
});
}
... and get this out:
Thread before: 1
Thread inside: 3
Hello stackoverflow!
Thread after: 3
Why? And also how I should set sync context if I want to use the same thread after await?
Why?
new SynchronizationContext()
by convention is the same as a null
SynchronizationContext
. Both "no SyncCtx" and "default SyncCtx" just queue work to the thread pool.
There is not a 1:1 relationship between SynchronizationContext
and a specific thread. For example:
- The WinForms UI
SynchronizationContext
will queue work to the single UI thread. AFAIK, the WinFormsSynchronizationContext
is a singleton, so there is a 1:1 mapping in this case. - The WPF
SynchronizationContext
will queue work to itsDispatcher
. Last time I checked, WPF will create a new instance for each top-level window, even if they all use the same thread. So there is a N:1 mapping. - The thread pool (default/
null
)SynchronizationContext
can queue work to any thread pool thread. If you don't create a defaultSynchronizationContext
instance, there is a 1:N mapping.
And also how I should set sync context if I want to use the same thread after await?
You'll need to use a custom SynchronizationContext
. I recommend using my AsyncContext
or AsyncContextThread
types, since that's not straightforward code to write.
这篇关于为什么同步上下文无法等待?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!