多线程(任务)的高效运行方法

时间:2020-11-09 05:59:10

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

我需要为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 * * * *");

这是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); 
    }
}

因此,每个作业都处理4个ID(例如,GenerateAll1分别以ID 1、11、21和31运行) 但是我发现这效率低下。 因为当GenerateById(11)花很长时间时,即使GenerateGeneb2作业已经完成,GenerateById(21)和GenerateById(31)也要等到GenerateById(11)完成后才能运行。

我想做的是像hangfire这样仅执行一项工作

recurringJobManager.AddOrUpdate(
       "GenerateAll1",
                () => serviceProvider.GetService<IGenerator>().GenerateAll(), "0 * * * *");

和GeneratAll()方法创建10个线程,每个线程都获取Id并运行GenerateById方法。 完成后,它将使用尚未生成的ID运行GenerateById。 因此,所有10个线程都将工作,直到生成所有数据设置为止。

请问有关这种情况的任何建议?

谢谢

1 个答案:

答案 0 :(得分:1)

Parallel.For对于您尝试执行的操作很有用。尚不清楚您对GenerateById()结果的意图是什么,因此我将由您自己确定。

从文档中

执行一个for循环,在该循环中可以并行运行迭代。

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