0

JSON を返すコントローラー メソッドがあります。コレクションをセッションから引き出し、コレクションから最初のアイテムを取得してから、コレクションから削除します。メソッドの開始時のカウントが 1 だった場合、現在は 0 です。

同じメソッドでセッションからコレクションを再度取得して、コレクション数が1未満かどうかを確認すると、そうです。

ここまでは簡単なこと。

後続のリクエストで、コレクションはセッションから再度プルされますが、カウントが予想どおり 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 に対してキーを設定)、同じ結果が得られました。他のリクエストの更新された値はありません。私の構成で同期が無効になっているようです。

このコードを2台のコンピューターでも試しましたが、同じ結果です。

4

2 に答える 2

1

開発者エラー。恥ずかしいですが、最後のタスクを処理した後、新しいタスクを作成し続けるというバグがありました。この質問を削除したくなりました:)

時間を割いてくれてありがとう、マルコム。

于 2012-01-20T22:39:37.760 に答える
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を呼び出してセッションをセットアップし、次にhttp://localhost:1631/home/GetCoordinatesTaskを 2 回呼び出します。

結果は

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 に答える