这是我第一次使用多线程进程,我很难理解事情的运作方式。
以下是我的情景:
我有一个大约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");
}
答案 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.
}