为什么同步上下文无法等待? [英] Why sync context is not working for await?

查看:60
本文介绍了为什么同步上下文无法等待?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此答案

默认情况下,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,WinForms SynchronizationContext是一个单例,因此在这种情况下有一个1:1映射 .
  • WPF SynchronizationContext将把工作排队到其Dispatcher.上一次我检查时,WPF将为每个顶级窗口创建一个新的 instance ,即使它们都使用相同的线程.这样就形成了N:1的映射.
  • 线程池(默认值/null)SynchronizationContext可以将工作排队到任何线程池线程中.如果您不创建默认的SynchronizationContext实例,则存在1:N映射.

还有,如果我想在等待后使用同一线程,该如何设置同步上下文?

您将需要使用自定义的SynchronizationContext.我建议使用我的 AsyncContextAsyncContextThread类型,因为这不是要编写的简单代码.

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 WinForms SynchronizationContext is a singleton, so there is a 1:1 mapping in this case.
  • The WPF SynchronizationContext will queue work to its Dispatcher. 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 default SynchronizationContext 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆