ContinueWith失去的SynchronizationContext [英] ContinueWith loses the SynchronizationContext

查看:108
本文介绍了ContinueWith失去的SynchronizationContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码片段中,的SynchronizationContext 丢失,并且因为这也是的CurrentCulture 的CurrentUICulture 日志()来自这个答案

In the snippet below, the SynchronizationContext is lost, and because of that also the CurrentCulture and CurrentUICulture. Log() comes from this answer.

public async Task<ActionResult> Index()
{
    Log("before GetAsync");
    await new HttpClient().GetAsync("http://www.example.com/")
        .ContinueWith(request =>
        {
            Log("ContinueWith");
            request.Result.EnsureSuccessStatusCode();
        }, TaskContinuationOptions.AttachedToParent);

    return View();
}

static void Log(string message)
{
    var ctx = System.Threading.SynchronizationContext.Current;
    System.Diagnostics.Debug.Print("{0}; thread: {1}, context: {2}, culture: {3}, uiculture: {4}",
        message,
        System.Threading.Thread.CurrentThread.ManagedThreadId,
        ctx != null ? ctx.GetType().Name : String.Empty,
        System.Threading.Thread.CurrentThread.CurrentCulture.Name,
        System.Threading.Thread.CurrentThread.CurrentUICulture.Name);
}

这是输出:

GetAsync之前;主题:56,背景:AspNetSynchronizationContext文化:NL,的UICulture:NL结果
  ContinueWith;主题:46,语境:文化:NL-BE,的UICulture:EN-US

before GetAsync; thread: 56, context: AspNetSynchronizationContext, culture: nl, uiculture: nl
ContinueWith; thread: 46, context: , culture: nl-BE, uiculture: en-US

GetAsync 之前,文化和UI文化有我在的Application_BeginRequest 设置的值。在 ContinueWith ,上下文丢失,文化设为什么是浏览器提供,和UI区域性设置为一些默认的。

Before the GetAsync, the culture and UI culture have the values I set in Application_BeginRequest. Inside the ContinueWith, the context is missing, the culture is set to what's provided by the browser, and UI culture is set to some default.

据我所知,一切都与 AspNetSynchronizationContext 应自动发生。这有什么错我的code?

From what I understand, everything with AspNetSynchronizationContext should be happening automatically. What's wrong with my code?

推荐答案

为了迫使延续调度请求上下文线程上,你需要指定的TaskScheduler 调度继续时,应使用

In order to force scheduling of the continuation on the request context thread, you need to specify the TaskScheduler that should be used when scheduling the continuation.

public async Task<ActionResult> Index()
{
    Log("before GetAsync");
    await new HttpClient().GetAsync("http://www.example.com/")
        .ContinueWith(request =>
        {
            Log("ContinueWith");
            request.Result.EnsureSuccessStatusCode();
        }, 
        TaskContinuationOptions.AttachedToParent,
        CancellationToken.None,
        TaskScheduler.FromCurrentSynchronizationContext());

    return View();
}

Howver,您使用等待自动编组到目前的延续的SynchronizationContext 。你应该能够做到这一点:

Howver, you are using await which automatically marshals continuations on to the current SynchronizationContext. You should be able to do this:

public async Task<ActionResult> Index()
    {
        Log("before GetAsync");
        HttpResponseMessage request = await new HttpClient().GetAsync("http://www.example.com/");

        //everything below here is you 'continuation' on the request context
        Log("ContinueWith");
        request.EnsureSuccessStatusCode();

        return View();
    }

这篇关于ContinueWith失去的SynchronizationContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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