启动数千名背景工作者的正确方法? - c#

我编写了一个程序,该程序扫描网络中大约10.000台计算机的正常运行时间,活动用户,空闲时间和ping。
该程序表现出色。通常在3分钟左右内检查所有计算机。
但是最近,该程序一直处于冻结状态。它已完成所有任务,但不会退出。
我像这样启动所有BackGroundWorkers:

foreach (DataRow computer in computerTable.Rows)
                {
                    //Added check to see if computer is in inputlist for inputfilemode
                    if (!inputFileMode || (inputFileMode && computerList.Contains(computer["ComputerName"].ToString())))
                    {
                        BackgroundWorker bw = new BackgroundWorker();
                        //Determine background jobs
                        bw.DoWork += bw_DoWork;
                        bw.RunWorkerCompleted += bw_RunWorkerCompleted;

                        bw.RunWorkerAsync(computer); //Start background worker
                        numberOfWorkers++;
                    }
                }


                int lastNr = 0;
                int skipHangingJobsCounter = 0;
                do
                {
                    lastNr = numberOfWorkers;
                    Thread.Sleep(1000);

                    Console.WriteLine("Tijd: " + DateTime.Now.ToString("yyyyMMdd-HH:mm:ss") + " #Jobs queued: " + numberOfWorkers.ToString() + " Jobs/sec: " + (lastNr - numberOfWorkers).ToString() + " -ForcedShutdowns: " + forcedReboots.ToString() + " -MSIEXEC Exceptions: " + machinesMSI.ToString()); //Report progress
                    if (lastNr - numberOfWorkers == 0)
                    {
                        skipHangingJobsCounter++;
                        if (skipHangingJobsCounter > 30) break; //Safety breakout if a worker hangs
                    }
                    else
                    {
                        skipHangingJobsCounter = 0;
                    }

                    //Timing break
                    double minutesRunning = DateTime.Now.Subtract(startOfJob).TotalMinutes;
                    if (minutesRunning > 13)
                    {
                        Console.WriteLine("Job is running for 14 minutes. Job will be cancelled. Jobs queued remaining: " + numberOfWorkers.ToString());
                        break;
                    }

                } while (numberOfWorkers > 0); //Wait till all jobs are finished

我想知道:这是启动和跟踪所有后台作业的最有效方法吗?创建列表数组更好吗?
我认为这会占用很多内存吗?

在do_work部分中,我有很多WMI查询,正常运行时间等。是否可能由于挂起WMI查询而导致程序无法退出?还有其他人尝试过吗?

所以基本上我有两个问题:

1-我是否以有效/正确的方式启动了后台工作人员?

2-线程中的WMI调用是否有可能导致程序无法退出?

更新:

我将代码重新编写如下。现在快了3倍。我仍然使用1个后台工作程序,但仅限于此,因此我可以对主线程提供反馈。我认为它应该工作的方式:)

主线程:

                    BackgroundWorker bw = new BackgroundWorker();
                bw.DoWork += bw_DoWork;
                bw.RunWorkerCompleted +=bw_RunWorkerCompleted;
                bw.RunWorkerAsync();

                int lastNr = numberOfWorkers;
                do
                {
                    lastNr = numberOfWorkers;
                    Thread.Sleep(1000); //Give feedback every second

                    Console.WriteLine("Tijd: " + DateTime.Now.ToString("yyyyMMdd-HH:mm:ss") + " #Jobs queued: " + numberOfWorkers.ToString() + " Jobs/sec: " + (lastNr - numberOfWorkers).ToString() + " -ForcedShutdowns: " + forcedReboots.ToString() + " -MSIEXEC Exceptions: " + machinesMSI.ToString()); //Report progress

                    //Timing break
                    double minutesRunning = DateTime.Now.Subtract(startOfJob).TotalMinutes;
                    if (numberOfWorkers < 3)
                    {
                        //We are waiting for 3 last workers. Give feedback which 3 thse are
                        foreach (Task t in taskArray)
                        {
                            if (t.Status == TaskStatus.Running)
                            {
                                Console.WriteLine("Waiting for " + taskList[t.Id]);
                            }
                        }
                    }
                    if (minutesRunning > 13)
                    {
                        Console.WriteLine("Job is running for 14 minutes. Job will be cancelled. Jobs queued remaining: " + numberOfWorkers.ToString());
                        break;
                    }

                } while (!jobDone); //Wait till all jobs are finished

后台工作

        static void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        JobLauncher();
    }

    static void JobLauncher()
    {


        foreach (DataRow computer in computerTable.Rows)
        {
            //Added check to see if computer is in inputlist for inputfilemode
            if (!inputFileMode || (inputFileMode && computerList.Contains(computer["ComputerName"].ToString())))
            {
                Task t = Task.Factory.StartNew(() => CheckComputer(computer));
                taskList.Add(t.Id, computer["ComputerName"].ToString());
                taskArray.Add(t);

                numberOfWorkers++;
            }
        }

        Task.WaitAll(taskArray.ToArray());
    }

参考方案

除了所有这些,您最好使用预定义的方法来检查所有任务是否已结束。您的代码很容易出错,并且很可能会关闭整个应用程序。为什么要为每台计算机启动1个线程? 10.000个线程?对我来说似乎太过分了。

我的建议是使用任务而不是后台工作人员。如果您具有网络I / O,则很有可能await这样做,从而提高整体性能。只需Task.WhenAll它们,您就会注意到它们何时准备就绪。

另一种方法是使用Parrallel库。您可以Parrallel.Foreach计算机列表,将它们拖到最多16个左右,.NET框架将为您进行所有循环和检查。

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

改造正在返回一个空的响应主体 - java

我正在尝试使用Retrofit和Gson解析一些JSON。但是,我得到的响应机构是空的。当我尝试从对象中打印信息时,出现NullPointerException。我确保URL正确,并且我也确保POJO也正确。我正在使用jsonschema2pojo来帮助创建POJO类。这是我要解析的JSON{ "?xml": { "@versi…

每个文件合并后添加换行 - python

我有很多类似以下内容的JSON文件:例如。1.json{"name": "one", "description": "testDescription...", "comment": ""} test.json{"name"…

Json到php,json_decode返回NULL - php

我正在用PHP进行JSON解析器的一些API,用于存储有关遗产的信息。我在解析时遇到问题,因为它返回的是NULL值而不是数组或对象。简单的JSON代码可以很好地解析,但是可以这样:{"success":true,"totalCount":1,"data":[{"id":99694…

将ajax的值存储到javascript变量中 - javascript

我有一个php文件,其中我从服务器获取数据。该php文件的输出是一个包含json格式数据的变量。PHP文件:<?php $dbHostName = "localhost"; $dbUserName = "venseld"; $dbUserPass = "wecuuu"; $dbName = &…