0

我有一个返回一些 JSON 的控制器方法。它将一个集合拉出会话,从集合中取出第一个项目,然后将其从集合中删除。如果方法开始时的计数为 1,则现在为 0。

如果我再次以相同的方法从会话中检索集合以检查集合计数是否小于一个,则它是。

到目前为止很简单的东西。

在随后的请求中,集合再次从会话中拉出,但不是预期的计数为 0,而是为 1。先前删除的项目尚未删除!为什么是这样?

尽管如果提出了足够多的请求,计数确实会归零。好像会话对象需要 30 秒左右才能在所有线程之间同步。

真的可以这样吗?MVC4(也可能是以前的版本?)是否有一些奇怪的会话同步问题?

我正在使用默认的 InProc 会话提供程序和设置。

这是日志:

Thread  Level   Logger  Message
23  DEBUG   ProjectMvc.Controllers.RpcController    Pre-processing - Tasks.Count: 1
23  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - SessionID: asaq1v5afu0pwz13at4a24hl
23  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - Tasks.Count: 0

16  DEBUG   ProjectMvc.Controllers.RpcController    Pre-processing - Tasks.Count: 1
16  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - SessionID: asaq1v5afu0pwz13at4a24hl
16  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - Tasks.Count: 0

23  DEBUG   ProjectMvc.Controllers.RpcController    Pre-processing - Tasks.Count: 1
23  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - SessionID: asaq1v5afu0pwz13at4a24hl
23  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - Tasks.Count: 0

24  DEBUG   ProjectMvc.Controllers.RpcController    Pre-processing - Tasks.Count: 1
24  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - SessionID: asaq1v5afu0pwz13at4a24hl
24  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - Tasks.Count: 0

9   DEBUG   ProjectMvc.Controllers.RpcController    Pre-processing - Tasks.Count: 1
9   DEBUG   ProjectMvc.Controllers.RpcController    Post processing - SessionID: asaq1v5afu0pwz13at4a24hl
9   DEBUG   ProjectMvc.Controllers.RpcController    Post processing - Tasks.Count: 0

14  DEBUG   ProjectMvc.Controllers.RpcController    Pre-processing - Tasks.Count: 1
14  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - SessionID: asaq1v5afu0pwz13at4a24hl
14  DEBUG   ProjectMvc.Controllers.RpcController    Post processing - Tasks.Count: 0

如果我无法弄清楚为什么会话中的集合没有针对其他请求进行更新,我将不得不解决它并将这些东西存储在数据库中。

这是代码:

    public ActionResult GetCoordinatesTask()
    {
        var user = Session["User"] as IUser;
        if (user == null)
        {
            Logger.LogError(this, "No user in session!");
            return Json(null, JsonRequestBehavior.AllowGet);
        }

        if (user.PhotoGeocodingTasks == null || user.PhotoGeocodingTasks.Count == 0)
            return Json(null, JsonRequestBehavior.AllowGet);

        lock (user.PhotoGeocodingTasks)
        {
            Logger.LogDebug(this, "Pre-processing - PhotoGeocodingTasks.Count" + user.PhotoGeocodingTasks.Count);

            var task = user.PhotoGeocodingTasks[0];
            if (!user.PhotoGeocodingTasks.Remove(task))
                Logger.LogError(this, "Could not remove geocoding task after picking it up!");

            var encodedTask = new Dictionary<string, string>
            {
                {"photoid", task.PhotoId.ToString(CultureInfo.InvariantCulture)},
                {"latlong", task.Latitude + "," + task.Longitide}
            };

            Logger.LogDebug(this, "Post processing - SessionID: " + Session.SessionID);
            Logger.LogDebug(this, "Post processing - PhotoGeocodingTasks.Count" + user.PhotoGeocodingTasks.Count);

            return Json(encodedTask, JsonRequestBehavior.AllowGet);
        }
    }

编辑

这是我在 web.config 上的会话:

<sessionState mode="InProc" customProvider="DefaultSessionProvider">
        <providers>
            <add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        </providers>
    </sessionState>

编辑 2

我还尝试将此任务数据也存储在 HttpRuntime.Cache 中(针对用户 ID 键入)并得到相同的结果。其他请求没有更新值。就像我的配置中禁用了同步一样。

我也在两台电脑上试过这段代码,结果一样。

4

2 回答 2

1

我在这里看不到这种行为。你能试试我的样品吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NLog;
using System.Globalization;
using System.Threading;

namespace Mvc4Application.Controllers
{
    public class GeoCodingTask
    {
       public string  Photoid{get;set;}
    }

    public class User
    {
        public List<GeoCodingTask> PhotoGeocodingTasks {get;set;}
    }

    public class HomeController : Controller
    {
        private static Logger _logger = LogManager.GetCurrentClassLogger();

        public ActionResult SetupCoordinatesTask()
        {   
                User  user = new User{ PhotoGeocodingTasks = new List<GeoCodingTask>()};
                 user.PhotoGeocodingTasks.Add(new GeoCodingTask{ Photoid= "id1"});
                 user.PhotoGeocodingTasks.Add(new GeoCodingTask { Photoid = "id2" });
                Session["User"] = user ;

            return View("GetCoordinatesTask");
        }

        public ActionResult GetCoordinatesTask()
        {
            User user = (User)Session["User"];
            if (user == null)
            {
                _logger.Error("No user in session!");
                return View();
            }
            if (user.PhotoGeocodingTasks == null )
                _logger.Debug("PhotoGeocodingTasks - null " );
            if (user.PhotoGeocodingTasks.Count == 0)
            {
                _logger.Debug("Pre-processing - PhotoGeocodingTasks.Count" + user.PhotoGeocodingTasks.Count);
                return View();
            }
            lock (user.PhotoGeocodingTasks)
            {
                _logger.Debug("Pre-processing - PhotoGeocodingTasks.Count" + user.PhotoGeocodingTasks.Count);
                var task = user.PhotoGeocodingTasks[0];
                if (!user.PhotoGeocodingTasks.Remove(task))
                    _logger.Error("Could not remove geocoding task after picking it up!");

                _logger.Debug("Post processing - SessionID: " + Session.SessionID);
                _logger.Debug("Post processing - PhotoGeocodingTasks.Count" + user.PhotoGeocodingTasks.Count);
                return View();
            }
        }

    }
}

我首先调用http://localhost:1631/home/SetupCoordinatesTask来设置会话,然后调用 2 次http://localhost:1631/home/GetCoordinatesTask

结果是

thread:19|2012-01-20 22:12:51.0492|DEBUG|Mvc4Application.Controllers.HomeController|Pre-processing - PhotoGeocodingTasks.Count2
thread:19|2012-01-20 22:12:51.0652|DEBUG|Mvc4Application.Controllers.HomeController|Post processing - SessionID: e4tawytx2mfq2msc3y2ajzl3
thread:19|2012-01-20 22:12:51.0652|DEBUG|Mvc4Application.Controllers.HomeController|Post processing - PhotoGeocodingTasks.Count1
thread:10|2012-01-20 22:13:01.0928|DEBUG|Mvc4Application.Controllers.HomeController|Pre-processing - PhotoGeocodingTasks.Count1
thread:10|2012-01-20 22:13:01.0928|DEBUG|Mvc4Application.Controllers.HomeController|Post processing - SessionID: e4tawytx2mfq2msc3y2ajzl3
thread:10|2012-01-20 22:13:01.0928|DEBUG|Mvc4Application.Controllers.HomeController|Post processing - PhotoGeocodingTasks.Count0
thread:15|2012-01-20 22:13:02.6698|DEBUG|Mvc4Application.Controllers.HomeController|Pre-processing - PhotoGeocodingTasks.Count0

你能简化你的代码并发布一个完整的示例吗?

于 2012-01-20T21:19:53.303 回答
1

开发者错误。尴尬,但我有一个错误,我在处理最后一个任务后继续创建一个新任务。我很想删除这个问题:)

感谢您的时间所有相同的马尔科姆。

于 2012-01-20T22:39:37.760 回答