C# 通过多线程(任务)运行方法的有效方法
我正在寻找运行多线程方法的最佳方法 下面是一个我想运行的方法C# 通过多线程(任务)运行方法的有效方法,c#,multithreading,asynchronous,task,hangfire,C#,Multithreading,Asynchronous,Task,Hangfire,我正在寻找运行多线程方法的最佳方法 下面是一个我想运行的方法 public async Task<IActionResult> GenerateById(int id) { //make a web request and save response to database using EF. return Json(new { success = true, message = "Worked" }); } public异步任务Generate
public async Task<IActionResult> GenerateById(int id)
{
//make a web request and save response to database using EF.
return Json(new { success = true, message = "Worked" });
}
public异步任务GenerateById(int-id)
{
//使用EF发出web请求并将响应保存到数据库。
返回Json(新的{success=true,message=“Worked”});
}
我需要运行Id为1到40的这个方法,目前,它由hangfire完成,有10个作业
在startup.cs中
recurringJobManager.AddOrUpdate("GenerateAll1",
() => serviceProvider.GetService<IGenerator>().GenerateAll(1), "0 * * * *");
recurringJobManager.AddOrUpdate("GenerateAll2",
() => serviceProvider.GetService<IGenerator>().GenerateAll(2), "0 * * * *");
recurringJobManager.AddOrUpdate("GenerateAll3",
() => serviceProvider.GetService<IGenerator>().GenerateAll(3), "0 * * * *");
....
recurringJobManager.AddOrUpdate("GenerateAll10",
() => serviceProvider.GetService<IGenerator>().GenerateAll(10), "0 * * * *");
recurringJobManager.AddOrUpdate(“GenerateAll1”,
()=>serviceProvider.GetService().GenerateAll(1),“0****”;
recurringJobManager.AddOrUpdate(“GenerateAll2”,
()=>serviceProvider.GetService().GenerateAll(2),“0****”;
recurringJobManager.AddOrUpdate(“GenerateAll3”,
()=>serviceProvider.GetService().GenerateAll(3),“0****”;
....
recurringJobManager.AddOrUpdate(“GenerateAll10”,
()=>serviceProvider.GetService().GenerateAll(10),“0****”;
这是GenerateAll
public async Task GenerateAll(int mod)
{
if (mod == 10)
{
mod = 0;
}
List<DataSetting> listsToUpdate = _unitOfWork.DataSetting.GetAll(r => r.Id%10 == mod ).ToList();
foreach (var list in listsToUpdate )
{
await GenerateById(list.Id);
}
}
公共异步任务生成器(int mod)
{
如果(mod==10)
{
mod=0;
}
List listsToUpdate=\u unitOfWork.dataset.GetAll(r=>r.Id%10==mod.ToList();
foreach(listsToUpdate中的变量列表)
{
等待GenerateById(list.Id);
}
}
因此每个作业处理4个Id(例如,GenerateAll1针对Id 1、11、21和31运行)
但我发现这是低效的。
因为当GenerateById(11)花费很长时间时,GenerateById(21)和GenerateById(31)在GenerateById(11)完成之前不会运行,即使GenerateAll2作业已经完成
我想做的是像这样通过hangfire运行一个作业
recurringJobManager.AddOrUpdate(
"GenerateAll1",
() => serviceProvider.GetService<IGenerator>().GenerateAll(), "0 * * * *");
recurringJobManager.AddOrUpdate(
“生成1”,
()=>serviceProvider.GetService().GenerateAll(),“0****”;
方法创建10个线程,每个线程获取Id并运行GenerateById方法。
完成后,它将使用尚未生成的id运行GenerateById。
因此,在生成所有数据设置之前,所有10个线程都在工作
我能得到一些关于这种情况的建议吗
感谢并行。因为对您正在尝试的操作非常有用。现在还不清楚您对
GenerateById()
的结果的意图,所以我将让您自己去弄清楚
从文档中:
执行for循环,迭代可以在其中并行运行
recurringJobManager.AddOrUpdate(
“生成1”,
()=>serviceProvider.GetService().GenerateAll(),“0****”;
公共异步任务GenerateAll()
{
Parallel.For(0,_unitOfWork.dataset.Length,
新的ParallelOptions(){MaxDegreeOfParallelism=10},
x=>GenerateById(_unitOfWork.dataset[x]).Result());
}
公共异步任务GenerateById(int id)
{
...
返回Json(新的{success=true,message=“Worked”});
}
为什么不为每个id创建一个任务
,一次启动所有id,然后等待整个集合?我想,这里不需要乱搞线程。类似于Parallel.For(0,40,x=>GenerateById(x))代码>工作?OP需要提供更多信息。这是否在Asp.net应用程序上?每个请求需要调用'GenerateById(int-id)`40次吗?嗨,杰瑞,谢谢你的建议。我应该提到GenerateById()方法。它发出web请求并将响应数据保存到数据库中,因此由EF完成。我得到了一个错误“在前一个操作完成之前,在这个上下文中开始了第二个操作”。你有什么想法我可以使用并行方法use EF吗?如果你想让所有线程访问同一个DbContext实例,那么你必须使用锁,这样一次只有一个线程访问它。如果与web请求相比,上下文上的操作速度很快,那么并行操作仍然有很大的好处。
recurringJobManager.AddOrUpdate(
"GenerateAll1",
() => serviceProvider.GetService<IGenerator>().GenerateAll(), "0 * * * *");
public async Task GenerateAll()
{
Parallel.For(0, _unitOfWork.DataSetting.Length,
new ParallelOptions() { MaxDegreeOfParallelism = 10 },
x => GenerateById(_unitOfWork.DataSetting[x]).Result());
}
public async Task<IActionResult> GenerateById(int id)
{
...
return Json(new { success = true, message = "Worked" });
}