ASP.NET会话在更新时线程之间不同步?
我有一个返回一些JSON的控制器方法。它将集合从会话中拉出,从集合中取出第一个项目,然后将其从集合中移除。如果方法开始时的计数为1,则现在为0 如果我再次使用相同的方法从会话中检索集合,以检查集合计数是否小于1,则为 到目前为止都很简单 在后续请求中,将再次从会话中提取集合,但集合的计数不是预期的0,而是1。以前删除的项目尚未删除!为什么会这样 尽管如果提出了足够的请求,计数最终确实为零。就好像会话对象在所有线程之间同步大约需要30秒 真的会这样吗?MVC4(也可能是以前的版本?)是否存在一些奇怪的会话同步问题 我正在使用默认的InProc会话提供程序和设置 这是日志:ASP.NET会话在更新时线程之间不同步?,asp.net,session,thread-safety,asp.net-mvc-4,Asp.net,Session,Thread Safety,Asp.net Mvc 4,我有一个返回一些JSON的控制器方法。它将集合从会话中拉出,从集合中取出第一个项目,然后将其从集合中移除。如果方法开始时的计数为1,则现在为0 如果我再次使用相同的方法从会话中检索集合,以检查集合计数是否小于1,则为 到目前为止都很简单 在后续请求中,将再次从会话中提取集合,但集合的计数不是预期的0,而是1。以前删除的项目尚未删除!为什么会这样 尽管如果提出了足够的请求,计数最终确实为零。就好像会话对象在所有线程之间同步大约需要30秒 真的会这样吗?MVC4(也可能是以前的版本?)是否存在一些奇
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);
}
}
public ActionResult getCoordinateTask()
{
var user=会话[“用户”]作为IUser;
if(user==null)
{
Logger.LogError(这是“会话中没有用户!”);
返回Json(null,JsonRequestBehavior.AllowGet);
}
if(user.PhotoGeocodingTasks==null | | user.PhotoGeocodingTasks.Count==0)
返回Json(null,JsonRequestBehavior.AllowGet);
锁定(用户.PhotoGeocodingTasks)
{
Logger.LogDebug(这是“预处理-PhotoGeocodingTasks.Count”+user.PhotoGeocodingTasks.Count);
var task=user.photogeocodingtask[0];
如果(!user.PhotoGeocodingTasks.Remove(任务))
Logger.LogError(这是“拾取后无法删除地理编码任务!”);
var encodedTask=新字典
{
{“photoid”,task.photoid.ToString(CultureInfo.InvariantCulture)},
{“latlong”,task.Latitude+,“+task.Longitide}
};
LogDebug(这是“后处理-SessionID:+Session.SessionID”);
LogDebug(这是“后处理-PhotoGeocodingTasks.Count”+user.PhotoGeocodingTasks.Count);
返回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键入),并得到了相同的结果。没有其他请求的更新值。这就像我的配置中禁用了同步一样
我也在两台计算机上尝试过这个代码,结果相同。我在这里看不到这种行为。你能试试我的样品吗
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();
}
}
}
}
您能简化代码并发布完整的示例吗?开发人员错误。令人尴尬,但我有一个bug,在处理完最后一个任务后,我一直在创建一个新任务。我很想删除这个问题:)
感谢您抽出时间访问所有相同的Malcom。会话与MVC无关。事实上,我不知道线程是否会同步,因为我的代码在一段时间后停止调用此方法:(我投票将此问题删除为“非建设性”。)因为你发现这实际上是开发人员的错误。哇,感谢你花时间在Malcom上。我复制了你的示例,它按预期工作,添加了一个任务,然后检索它并将其从会话中删除。在你回复之前,我还编写了一些新代码,将任务粘贴到HttpRuntime缓存中,并得到了与没有跨线程相同的坏效果/请求更新(在阅读了说明会话无论如何都存储在缓存下的文档后才有意义)。感觉像是配置问题。我比较了两个应用程序之间的web.configs,并尝试了一些差异,但结果相同。Jay-开发者错误-显然不是:)我知道,令人震惊的行为。
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