处理多线程进程

时间:2014-12-08 16:33:07

标签: c# vmware

这是我第一次使用多线程进程,我很难理解事情的运作方式。

以下是我的情景:

我有一个大约15长的服务器列表。然后,我将每个服务器放在它所属的vCenter列表中。因此,如果我有大约15个服务器和5个vCenters,那么它必须至少循环3次以通过serverList将每个服务器设置为其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方法时拆分线程。

EDIT2

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

这是我的新功能,但是你可以根据你的平行理念&#34;开始getData&#34;在End getData之前输出了不止一次,这让我觉得还有另一个线程在这旁边运行。有任何想法吗?谢谢你的帮助!

编辑3

List<Server> Queue = [server1]... [server15]

List<vCenter> vCenters = [vCenter1] ... [vCenter5]

有15个服务器和5个vCenters。

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

1 个答案:

答案 0 :(得分:1)

从根本上说,你走错了路;您需要为每个vCenter创建一个线程,而不是让您创建的线程循环通过vCenters列表。您也可以使用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.
    }