Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过多线程(任务)运行方法的有效方法_C#_Multithreading_Asynchronous_Task_Hangfire - Fatal编程技术网

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" });
}