问题描述
我对线程技术还很陌生,所以如果这没有太大意义或者我遗漏了一些明显的东西,我会深表歉意。基本上,我在内存中有一个列表List<Patients>
,其中包含4个条目。
public class PatientAreaController : Controller
{
private List<Patient> patients = new List<Patient>()
{
new Patient { ID = 0,FamilyName = "Hill",Givenname = "Chris",LastSelectedDate = DateTime.Now },new Patient { ID = 1,FamilyName = "Stephens",Givenname = "Sion",LastSelectedDate = DateTime.Now },new Patient { ID = 2,FamilyName = "Murray",Givenname = "Thomas",new Patient { ID = 3,FamilyName = "Dupre",Givenname = "Pierre",LastSelectedDate = DateTime.Now }
};
然后,我有一个在System.Threading.Timer
上运行的async
,它调用一种方法来更改所述列表。这样可以永远在后台运行。
public ActionResult Index(string sortOrder)
{
Timer timer = new Timer(async (e) =>
{
await Task.Delay(10000);
UpdatePatientsList();
},null,10000);
return View(patients);
}
方法UpdatePatientsList()
:
private void UpdatePatientsList()
{
switch (addOrRemovePatient)
{
case "Add":
patients.Add(threadPatient);
break;
case "Remove":
Random rnd = new Random();
int randomId = rnd.Next(3);
threadPatient = patients.Find(x => x.ID.Equals(randomId));
patients.Remove(threadPatient);
break;
default:
break;
}
if (addOrRemovePatient == "Remove")
addOrRemovePatient = "Add";
else
addOrRemovePatient = "Remove";
}
这个想法是每10秒钟调用一次此方法,该方法将从列表中删除一个项目,然后10秒钟后将其重新添加。
然后,在客户端上,我有一个setInterval调用,返回到服务器以检索此列表。
setInterval(function () {
$("#dvPatientListResults").hide().load('@(Url.Action("GetFullAndPartialviewmodel","PatientArea",Request.Url.Scheme))').fadeIn('slow');
},10000);
此setInterval
每10秒刷新一次表,并使用GetFullAndPartialviewmodel
方法调用中的PatientList中的数据:
public ActionResult GetFullAndPartialviewmodel()
{
return PartialView("PatientList",patients);
}
但是,检索到的列表从不显示计时器进行的更新,并且始终返回4个项目。如果我单步执行代码,则可以清楚地看到计时器线程具有包含3个项目的列表,但是客户端调用始终返回完整列表4。
我想这是因为计时器位于单独的异步线程上,而这不是ajax回调所引用的内容。我最初的想法是,也许我需要以某种方式将计时器线程合并回主线程,以获取带有更新列表的主线程-但是,即使这件事我也无法弄清楚该如何做。有什么方法可以实现我想要的?
我随后建议SignalR值得研究-但是我对此有时间限制,没有真正的时间弄清楚SignalR(尽管我可以试一试!)
解决方法
因此,您的主要问题是ASP.NET控制器是临时的……这意味着它们是针对指向该控制器的每个请求而新建的。
针对您的问题的快速解决方案是:
private static List<Patient> patients = new List<Patient>()
{
new Patient { ID = 0,FamilyName = "Hill",GivenName = "Chris",LastSelectedDate = DateTime.Now },new Patient { ID = 1,FamilyName = "Stephens",GivenName = "Sion",LastSelectedDate = DateTime.Now },new Patient { ID = 2,FamilyName = "Murray",GivenName = "Thomas",new Patient { ID = 3,FamilyName = "Dupre",GivenName = "Pierre",LastSelectedDate = DateTime.Now }
};
将该列表设为static
,无论创建多少个控制器,该列表将在应用程序的生存期内持续存在。
之前发生的事情是每次您发出请求时都会返回一个新列表。
一个旁注:您应该look in to IHostedService
或BackgroundService
来做这些事情。在控制器内部执行此操作不太像“控制器”。