首页 > 解决方案 > 通过多线程(任务)运行方法的有效方法

问题描述

我正在寻找运行具有多个线程的方法的最佳方法。

这是我想运行的方法

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 个作业。

在启动.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) 需要很长时间时,即使 GenerateAll2 作业已经完成,GenerateById(21) 和 GenerateById(31) 也不会运行,直到 GenerateById(11) 完成。

我想要做的是只用hangfire运行1个工作,比如

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

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

我可以就这种情况获得任何建议吗?

谢谢

标签: c#multithreadingasynchronoustaskhangfire

解决方案


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

推荐阅读