0

我对这个问题有点沮丧:

我有一个管理一些要下载的文件的网站,因为这些文件非常大,必须在文件夹中组织然后压缩,我构建了一个 Ajax 结构,在后台完成这项工作,当这些文件准备好下载时,这个作业改变了用户会话中对象的状态(bool isReady = true,就这么简单)。

为了实现这一点,当用户点击“下载”时,一个 jquery Post 被发送到一个 API,这个 API 启动“组织者”工作并完成代码(主线程,请求范围的),留下一个后台线程做魔法(太美了哈哈)。

这个“组织者”作业是一个后台线程,通过参数接收 HttpSessionState (HttpContext.Current.Session)。它组织和压缩文件,创建下载链接,最后使用 param 接收到的 HttpSessionState 更改会话中的对象。

当我使用会话“InProc”模式时,这很有效(我很高兴在测试后在生产中部署这种艺术和平)。

但是,当我在生产环境中部署项目时,我的噩梦就开始了,因为我们在这个环境中使用“StateServer”模式。在这些环境中,不会应用更改。

到目前为止,我注意到的是,在 StateServer 中,当更改发生在用户请求结束后(启动线程的线程)时,我在后台线程中所做的每项更改都不会“提交”到会话中。如果我写一个 thread.join() 来等待线程完成,则应用在线程内部所做的更改。

我正在考虑使用数据库来存储这些值,但是,我会失去一些性能:(

[HttpPost]
        [Route("startDownloadNow")]
        public void StartDownloadNow(DownloadStatusProxy input)
        {
            //some pieces of code...
            ... 

            //add the download request in the user session
            Downloads.Add(data);

            //pass the session as parameter to the thread
            //cause the thread itself don't know the current httpcontext session
            HttpSessionState session = HttpContext.Current.Session;
            Thread thread = new Thread(() => ProccessDownload(data, session));
            thread.Start();
            //here, if I put a thread.join(), the changes inside the thread are applied correctly, but I can't do this, otherwise, it ceases to be ajax
        }

private void ProccessDownload(DownloadStatus currentDownload, HttpSessionState session)
        {
            List<DownloadStatus> listDownload = ((List<DownloadStatus>)session["Downloads"]);

            try
            {
                //just make the magic...
                string downloadUrl = CartClient.CartDownloadNow(currentDownload.idRegion, currentDownload.idUser, currentDownload.idLanguage, currentDownload.listCartAsset.ToArray(), currentDownload.listCartAssetThumb.ToArray());

                listDownload.Find(d => d.hashId == currentDownload.hashId).downloadUrl = downloadUrl;
                listDownload.Find(d => d.hashId == currentDownload.hashId).isReady = true;
                //in this point, if I inspect the current session, the values are applied but, in the next user request, these values are in the previous state... sad... .net bad dog...
            }
            catch (Exception e)
            {
                listDownload.Find(d => d.hashId == currentDownload.hashId).msgError = Utils.GetAllErrors(e);
                LogService.Log(e);
            }
            //this was a desesperated try, I retrieve the object, manipulated and put it back again to the session, but it doesn't works too...
            session["Downloads"] = listDownload;
        }
4

0 回答 0