【问题标题】:Issue with Multithreading, saying it finished before the tasks haven't多线程问题,说它在任务没有完成之前完成
【发布时间】:2020-04-21 21:02:26
【问题描述】:

我编写了一个 void 来处理 selenium 网页浏览的多个线程。问题是现在,例如,如果我输入 4 个任务和 2 个线程。程序在完成 2 个任务时说它完成了。

编辑:基本上我希望程序等待任务完成而且我希望如果一个线程完成但另一个线程正在运行并且有任务要做,它直接开始另一个任务,而不是等待第二个线程结束。

感谢并为代码感到抱歉,以便快速将其作为示例进行展示。

    {
static void Main(string[] args)
    {
        Threads(4, 4);
        Console.WriteLine("Program has finished");
        Console.ReadLine();
    }

    static Random ran = new Random();
    static int loop;
    public static void Threads(int number, int threads)
    {
        for (int i = 0; i < number; i++)
        {
            if (threads == 1)
            {
                generateDriver();
            }
            else if (threads > 1)
            {
            start:
                if (loop < threads)
                {
                    loop++;
                    Thread thread = new Thread(() => generateDriver());
                    thread.Start();

                }
                else 
                {
                    Task.Delay(2000).Wait();
                    goto start;
                }
            }
        }
    }


    public static void test(IWebDriver driver)
    {
        driver.Navigate().GoToUrl("https://google.com/");
        int timer = ran.Next(100, 2000);
        Task.Delay(timer).Wait();
        Console.WriteLine("[" + DateTime.Now.ToString("hh:mm:ss") + "] - " + "Task done.");
        loop--;
        driver.Close();
    }

    public static void generateDriver()
    {
        ChromeOptions options = new ChromeOptions();
        options.AddArguments("--disable-dev-shm-usage");
        options.AddArguments("--disable-extensions");
        options.AddArguments("--disable-gpu");
        options.AddArguments("window-size=1024,768");
        options.AddArguments("--test-type");

        ChromeDriverService service = ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
        service.HideCommandPromptWindow = true;
        service.SuppressInitialDiagnosticInformation = true;

        IWebDriver driver = new ChromeDriver(service, options);
        test(driver);
    }

【问题讨论】:

  • 我添加了代码@LarsTech
  • 您使用Thread 而不是Task 有什么原因吗?对于任务,您只需调用 Task.WaitAll
  • 另外你为什么使用goto而不是第二个for循环?
  • @UnholySheep 如果我有更多任务,我认为我不能使用 waitall?我想我之前尝试过,但没有成功。
  • 我尝试了很多方法,例如添加另一个 for 循环,但结果出现了其他问题。

标签: c# multithreading task


【解决方案1】:

手动跟踪正在运行的线程,等待它们完成并重用已经完成的线程并非易事。
然而,.NET 运行时提供了现成的解决方案,您应该更愿意自己处理它。
实现所需结果的最简单方法是使用Parallel.For 循环并设置MaxDegreeOfParallelism,例如:

public static void Threads(int number, int threads)
{
    Parallel.For(0, number,
                 new ParallelOptions { MaxDegreeOfParallelism = threads },
                 _ => generateDriver());
}

如果你真的想手动完成,你需要使用Thread(或Task)的数组并不断迭代它们,检查它们是否已经完成,以及它们是否用新线程替换它们。这需要比Parallel.For 解决方案更多的代码(并且不太可能表现得更好)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多