处理多线程进程

本文关键字:进程 多线程 处理 | 更新日期: 2023-09-27 18:33:28

这是我第一次使用多线程进程,我很难理解事情是如何工作的。

这是我的方案:

我有一个大约 15 长的服务器列表。然后,我将每台服务器按其所属的 vCenter 放在一个列表中。因此,如果我有大约 15 台服务器和 5 个 vCenter,那么它必须至少遍历 serverList 3 次才能将每个服务器设置为其 vCenter。执行下面的代码后,它会从服务器列表中删除服务器。

List<Server> serverList = new List<Server>();
//populate vCenters using the serverList
foreach(vCenter v in vCenters)
{ 
     //Connect to the vCenter and bring back data
     //remove the server from the serverList
}

问题是每个调用都没有等待前一个调用完成,因此 serverList 不一致,因为第一个服务器连接然后第二个服务器连接,然后第一个服务器带回数据。显然,这里正在进行一些多线程。但是,我希望能够说让每个 vCenter 连接并带回数据,并推迟其他所有内容,直到所有 vCenter 都带回数据。谁能给我一个关于如何做到这一点的好建议?我已经查看了任务和线程,但它似乎没有按照我的预期去做。

编辑

这是我目前如何处理它

public void getData()
{
    foreach(vCenter vCenter1 in vCenters)
    {
         VimClient client = connectToVC(vCenter1);
         NameValueCollection vmFilter = new NameValueCollection();
         vmFilter.Add("name", hostName);
         VirtualMachine vm = (VirtualMachine)client.FindEntityView(typeof(VirtualMachine), null, vmFilter, null);
         Console.WriteLine("cpu", getVMSpec(vm, "vCPU"));
         Console.WriteLine("mem", getVMSpec(vm, "Mem"));
    }
}
public String getVMSpec(VirtualMachine vm, String type)
    {
        if(type.Equals("vCPU"))
            return vm.Summary.Config.NumCpu.ToString();
        return vm.Summary.Config.MemorySizeMB.ToString();
    }
Action<object> action = (object obj) =>
{
    getData();
};
System.Threading.Tasks.Task t1 = System.Threading.Tasks.Task.Factory.StartNew(action, "gettingData");
t1.Wait();

理想情况下,getData 会对每个 vCenter 执行多线程处理,并将数据带回一个线程以继续处理应用程序,并且仅在调用 getData 方法时拆分线程。

编辑2

        while (Queue.Count > 0 || isVCentersEmpty() == false)
        {
            setVCenters(); // sets the vCenter buckets to any available servers from the Queue
            Console.WriteLine("Begin getData");
            var result = Parallel.ForEach(vCenters, getData);               
            while (!result.IsCompleted)
            {
                Console.WriteLine("gettingData...");
            }
            Console.WriteLine("End getData");
        }

这是我根据您的平行想法的新功能,但是"begin getData"在End getData之前被多次输出,这让我认为还有另一个线程在旁边运行。 有什么想法吗? 感谢您的帮助!

编辑 3

List<Server> Queue = [server1]... [server15]
List<vCenter> vCenters = [vCenter1] ... [vCenter5]

有 15 台服务器和 5 个虚拟中心。

while (Queue.Count > 0 || isVCentersEmpty() == false)
{
    setVCenters(); // sets the vCenter buckets to any available servers from the Queue
    Console.WriteLine("Begin getData");
    var result = Parallel.ForEach(vCenters, rightsize);               
    while (!result.IsCompleted)
    {
        Console.WriteLine("Getting Data...");
    }
    Console.WriteLine("End getData");
 }

处理多线程进程

从根本上说,您走错了路;您需要为每个 vCenter 创建一个线程,而不是让您创建的线程遍历 vCenter 列表。您还可以使用 TPL 来使用机器的核心,这可能会使其更容易理解。

更改 getData 以接受 vCenter 作为参数:

    public void getData(vCenter v)
    {
        VimClient client = connectToVC(v);
        NameValueCollection vmFilter = new NameValueCollection();
        vmFilter.Add("name", hostName);
        VirtualMachine vm = (VirtualMachine)client.FindEntityView(typeof(VirtualMachine), null, vmFilter, null);
        Console.WriteLine("cpu", getVMSpec(vm, "vCPU"));
        Console.WriteLine("mem", getVMSpec(vm, "Mem"));
    }

然后,您可以让 TPL 出去并按如下方式处理每个 vCenter:

    var result = Parallel.ForEach(vCenters, getData);
    while (!result.IsCompleted)
    {
        //do some other work; this is your main controlling thread.
    }