【问题标题】:Initializing culture in an asynchronous action complete在异步操作中初始化区域性完成
【发布时间】:2012-01-20 20:51:47
【问题描述】:

我正在使用 ASP.NET MVC 3。 一旦我决定将我的一些同步操作更改为异步操作。在此之前,我创建了一个示例异步操作来测试它是否可以正常工作。是这样的:

    public void SampleAsync()
    {
        AsyncManager.OutstandingOperations.Increment();
        var task = System.Threading.Tasks.Task.Factory.StartNew(() => DoStuff());
        task.ContinueWith(t =>
        {
            AsyncManager.Parameters["pars"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });
    }

    private object DoStuff()
    {
        System.Threading.Thread.Sleep(20000);
        return null;
    }

    public ActionResult SampleCompleted(object pars)
    {
        return View();
    }

但是这个动作不能异步工作!这绝对是同步的。至少,它作为传统操作阻止了其他请求(在运行时)。经过几个小时的调查,我发现问题出在我初始化当前文化的 asax 中:

    protected void Application_AcquireRequestState(object sender, EventArgs e)
    {
        CultureInfo ci;
        //It's important to check whether session object is ready
        if (HttpContext.Current.Session != null)
        {
            ci = (CultureInfo)this.Session["Culture"];
            //Checking first if there is no value in session 
            //and set default language 
            //this can happen for first user's request

            if (ci == null)
            {
                ci = GetCultureFromCookie();
                this.Session["Culture"] = ci;
            }
            if (ci == null)
            {
                ci = GetStandardCulture();
                this.Session["Culture"] = ci;
            }
        }
        else
        {
            ci = GetCultureFromCookie();
            if (ci == null) ci = GetStandardCulture();
        }
        //Finally setting culture for each request
        Thread.CurrentThread.CurrentUICulture = ci;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
    }

当我注释掉这个方法时,一切都开始正常工作了。我认为问题与从操作完成线程访问 HttpContext.Current 有关。但是在这种情况下,我应该如何初始化用户当前的文化呢?

【问题讨论】:

    标签: asp.net asp.net-mvc-3 asynchronous localization


    【解决方案1】:

    下面一行是问题:

    this.Session["Culture"] = ci;
    

    您正在写入会话。在 ASP.NET 中,会话不是线程安全的。出于这个原因ASP.NET synchronizes access 给它。这基本上意味着,如果您点击一个 ASP.NET 处理程序,该处理程序从 来自同一会话的 2 个并行请求写入会话,ASP.NET 将简单地按顺序执行它们。

    不要误会我的意思。这并不意味着来自 2 个不同用户的两个并行请求将按顺序执行。它们将完全平行。只是我假设您对该控制器操作运行了 2 个并行 AJAX 请求,并且您观察到了 FireBug 或其他任何行为中的行为。由于 2 个 AJAX 请求来自同一个会话,并且由于您写入会话,因此您被破坏了,您的请求无法并行执行。

    你必须找到另一种处理文化的方法。 Cookie 或 url 参数(在 SEO 方面更好)作为一个不错的选择浮现在脑海中。而且由于会话无论如何都是坏事,因此摆脱它们只会对您的应用程序有益。

    在 ASP.NET MVC 3 中,您可以使用 SessionState 属性来指示控制器操作将不使用会话,或者它只会从中读取:

    [SessionState(SessionStateBehavior.ReadOnly)]
    public class FooController: AsyncController
    {
    
    }
    

    现在您可以并行处理来自同一会话的请求。显然,每次尝试写入会话都会引发异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多