c# - ContinueWith 丢失 SynchronizationContext

标签 c# asp.net asp.net-mvc async-await c#-5.0

在下面的代码片段中,SynchronizationContext 丢失了,因此 CurrentCultureCurrentUICulture 也丢失了。 Log() 来自 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);
}

这是输出:

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

GetAsync 之前,culture 和 UI culture 具有我在 Application_BeginRequest 中设置的值。在 ContinueWith 中,缺少上下文,文化设置为浏览器提供的内容,UI 文化设置为一些默认值。

据我所知,所有与 AspNetSynchronizationContext 相关的事情都应该自动发生。我的代码有什么问题?

最佳答案

为了在请求上下文线程上强制调度延续,您需要指定调度延续时应该使用的 TaskScheduler

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();
}

但是,您使用的是 await,它会自动将延续编码到当前的 SynchronizationContext。你应该能够做到这一点:

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();
    }

关于c# - ContinueWith 丢失 SynchronizationContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23213941/

相关文章:

应用程序池的 C# .NET 单例生活

c# - 哪个是重定向 URL 的最佳方式?我们应该使用 Response.Redirect 还是有其他重定向命令?

C# 如何将放置变量添加到资源字符串中

c# - 构建验证服务层

javascript - ASP 脚本转 VB

html - Asp.net 菜单的最后一个子菜单显示在右侧

c# - 使用 ODAC 12c 第 4 版和 EF 6 将 Oracle 数据库导入 Entity Framework 模型时如何解决问题?

c# - Telerik TreeView |使用 NodeTemplate 时,NodeExpand 事件提供了错误的节点值

c# - ASP.NET MVC 网络 API : application/xml PUT request body is null on server side

asp.net-mvc - 构建新的大型 ASP.NET MVC2 plus EF4 VS2010 解决方案的最佳实践?