3

我对 MVC 很陌生,所以如果我遗漏了什么,请原谅我。

在我的一个控制器中,我启动了一个类,该类进行一些处理并输出如下字符串:

[HttpPost]
public ActionResult Check(string reg)
{
    string sCarmodel;
    GetRegInfo gri = new GetRegInfo(reg, out sCarmodel);
    Session["test"] = sCarmodel;

    return View("Check");
}

到目前为止一切顺利,sCarmodel 的输出正确存储在 Session 中,稍后可以在 View 中访问它。但是,我需要将该类放在一个单独的线程中,因为它需要一些时间来完成它并且我想返回视图 aschyncronosly。所以我尝试了这个:

[HttpPost]
public ActionResult Check(string reg)
{
    var getreginfoThread = new Thread(
        () =>
        {
            string sCarmodel;
            GetRegInfo gri = new GetRegInfo(reg, out sCarmodel);
            Session["test"] = sCarmodel;
        }
        );

    getreginfoThread.Start();

    return View("Check");
}

我知道我可以将“sCarmodel”的值从类本身存储在数据库中,但我正在寻找一种跳过使用数据库的方法。使用线程,sCarmodel的值没有存储在Session中,null当我尝试检索它时,Session是稍后的。

任何人都可以就我如何在线程中访问类中的值提供一些建议吗?

谢谢!

编辑: 问题解决了,谢谢大家的建议!

4

7 回答 7

3

在处理请求期间将自定义对象放入 Session 中。

将此自定义对象的引用传递给后台线程。

在后台线程中设置自定义对象的属性。

确保进行任何必要的同步。

于 2013-08-03T12:23:59.030 回答
1

您需要以某种方式将会话传递给后台线程。例如,请参见此处

顺便说一句,你为什么不使用任务并行库

于 2013-08-03T11:58:21.720 回答
0

并不是说值没有存储在 Session 中。这是。问题是您的代码继续与您创建的线程并行执行,并且当它访问Session["test"]它时,它尚未由您的线程分配。你必须以某种方式重新组织你的代码。此外,不建议在 asp.net 应用程序中启动线程,因为它非常占用资源。

编辑

看来它真的没有设置 Session 变量。如果你真的想这样做,你可以使用CallContext

CallContext.LogicalSetData("CurrentSession", Session);

var getreginfoThread = new Thread(
    () =>
    {
        string sCarmodel;
        GetRegInfo gri = new GetRegInfo(reg, out sCarmodel);
        var session = (HttpSessionState)CallContext.LogicalGetData("CurrentSession");

        session["test"] = sCarmodel;
    }
    );

getreginfoThread.Start();

return View("Check");

您将不得不以某种方式等待此数据不为空,然后使用它Session["test"]

于 2013-08-03T11:43:42.177 回答
0

HttpContext Session 对象的父/所有者对象不会传输到新线程,因此您的 Session 不能在主线程以外的线程中访问。

我建议您使用 async/await 从您的线程返回 sCarmodel 并将其设置为您在主线程中的 Session。

于 2013-08-03T12:09:37.333 回答
0

我建议您不要在线程中使用 Session 对象,因为它不是线程安全的。在 ASP.NET 中,每个请求都有自己的线程和会话。

您从未描述过真正的问题(不幸的是),所以我真的不知道您要解决什么,但是手动启动一个新线程并将数据放入 Session 无论如何都不是解决方案。

如果您想异步执行操作以让 Web 服务器在后台执行某些操作时为其他客户端提供服务,请查看异步控制器: http ://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous -aspnet-mvc-4 中的方法

同样,了解您尝试实现的目标以提出适当的解决方案非常有用。

于 2013-08-03T13:25:57.673 回答
0

我通过在 TempData 中存储类的实例解决了我的问题。此外,我使用更好的任务而不是线程。这是我的解决方案:

[HttpPost]
        public ActionResult GetRegInfo(string reg)
        {
            var gri = new GetRegInfo(reg);
            TempData["GetRegInfo"] = gri;

            Action<object> action = (object obj) => gri.Start();
            var t1 = new Task(action, "GetRegInfo");   
            t1.Start();

            return View("bilforsakring");
        }

后来我使用带有 Ajax 的 JavaScript 计时器并获得如下值:

[OutputCache(NoStore = true, Duration = 0)]
        public ActionResult GetRegInfoAjax()
        {
            if (TempData["GetRegInfo"] != null)
            {
                var g = (GetRegInfo)TempData["GetRegInfo"];  
                return Content(g.sCarmodel);
            }
            else
            {
                return Content("null");
            }
        }
于 2013-08-03T13:38:06.193 回答
0

但是,我需要将该类放在一个单独的线程中,因为它需要一些时间来完成它并且我想返回视图 aschyncronosly。

错误的。这是解决这个问题的完全错误的方法。在 ASP.NET 应用程序中,当有更多工作要做时,您永远不应该返回,除非您已经将该工作保存到持久存储中。

将工作保存在内存中(即,使用线程或任务)是一种不正确的解决方案。

The correct solution is to use persistent storage (e.g., Azure Queue, MSMQ, or WebSphere MQ) to store the work to be done and then have a separate service which reads that queue, takes the appropriate action, and stores the results in another persistent data structure. You can then have the client poll (e.g., HTTP request) the "result" data structure and/or notify the client (e.g., SignalR) when the result is saved.

I go into more details on my blog, and also have some example code to use there if you are absolutely sure that you want to take the unsafe route.

于 2013-08-03T15:31:24.633 回答