处理多线程进程
本文关键字:进程 多线程 处理 | 更新日期: 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.
}