创建到WMI的异步选择并等待其完成 [英] Creating async selects to WMI and wait to their completion
问题描述
我读了很多关于异步方法的文章,但仍然...对此我有些困惑.因此,也许有人可以帮助我解决我的问题.现在,我的代码没有引发任何错误,但是我知道我的代码不好,因为我使用了异步void,所以我等不及要完成所有任务.
I read a lot of posts about async methods, but still... I'm a little confused about this. So maybe someone can help me with my case. Right now my code doesn't throw any error, but I know that my code is not good, cause I use async void and I can't wait for all my task to be completed.
所以,有人可以帮我编辑此代码:
So, can someone please help me edit this code:
在我的表单类中,创建关系:
In my form class, I create Relation:
Relation rel = new Relation(cb_MachineToConnect.Text);
在关系类中:
public Relation(string machineAddress)
{
isAsctive = true;
idCount++;
relationID = idCount;
machine = new Machine(machineAddress);
//I'm using WMI for gettig data from remote machine
scope = new ManagementScope(string.Format("\\\\{0}\\root\\cimv2", machineAddress));
scope.Options.Timeout = TimeSpan.FromSeconds(timeOut);
//In this method, I need run async part of code - WMI selects
LoadMachineData();
}
LoadMachineData方法代码:
LoadMachineData methode code:
private async void LoadMachineData()
{
try
{
scope.Connect();
try
{
//List<Task> taskList = new List<Task>();
foreach (KeyValuePair<SelectQueryName, SelectQuery> select in SelectQueryes)
{
//And this is it.. I need to run this methods async for better performance. SelectFromWMI is in Relation class and SetWMIproiperties is in Machine class
await Task.Run(() => machine.SetWMIProperties(select.Key, SelectFromWMI(select.Value, scope)));
//taskList.Add(t);
//machine.SetWMIProperties(select.Key, SelectFromWMI(select.Value, scope));
}
//I also want to wait for all created Tasks completion, but with this code it is not possible
//Task.WaitAll(taskList.ToArray());
}
catch (Exception ex)
{
EventNotifier.LogOnScreen(string.Format("{0}, viz: {1}", ErrorList.GetEIbyID(15).definition, ex.Message));
EventNotifier.Log(ex, ErrorList.GetEIbyID(15));
}
}
catch (Exception ex)
{
EventNotifier.LogOnScreen(string.Format("{0}, viz: {1}", ErrorList.GetEIbyID(16).definition, ex.Message));
EventNotifier.Log(ex, ErrorList.GetEIbyID(17));
}
}
机器类中的SetWMIProperties(...)
SetWMIProperties(...) in Machine class:
public void SetWMIProperties(SelectQueryName queryName, List<Dictionary<string, string>> propertiesData)
{
foreach (Dictionary<string, string> result in propertiesData)
{
switch (queryName)
{
case SelectQueryName.DiskModel:
disks.Add(result["Model"]);
break;
case SelectQueryName.Drives:
drives.Add(new Drive { Name = result["Name"], FreeSpace = Convert.ToInt64(result["FreeSpace"]), Size = Convert.ToInt64(result["Size"]) });
break;
case SelectQueryName.OS:
operatingSystem = new OS { BuildNumber = result["BuildNumber"], ProductName = result["Caption"], BitVersion = (result["OSArchitecture"].Contains(((int)OSBitVersion.Win32).ToString())) ? OSBitVersion.Win32 : OSBitVersion.Win64 };
break;
case SelectQueryName.Processor:
processor = result["Name"];
break;
case SelectQueryName.RAM:
ram = new RAM { TotalVisibleMemorySize = Convert.ToInt64(result["TotalVisibleMemorySize"]), FreePhysicalMemory = Convert.ToInt64(result["FreePhysicalMemory"]) };
break;
}
}
}
Relation类中的WMI select方法(实际上,该方法应该是真正异步的,因为WMI select有时可能真的很慢):
And the WMI select method in Relation class (in fact, this method should to be truly async, cause WMI select can sometimes be really slow):
private static List<Dictionary<string, string>> SelectFromWMI(SelectQuery select, ManagementScope wmiScope)
{
List<Dictionary<string, string>> result = new List<Dictionary<string, string>>();
ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiScope, select);
ManagementObjectCollection objectCollection = searcher.Get();
foreach (ManagementObject managementObject in objectCollection)
{
result.Add(new Dictionary<string, string>());
foreach (PropertyData property in managementObject.Properties)
{
result.Last().Add(property.Name, property.Value.ToString());
}
}
return result;
}
推荐答案
要等待所有任务,可以使用Task.WhenAll()
:
To await all your tasks you can use Task.WhenAll()
:
private async void LoadMachineData()
{
try
{
scope.Connect();
try
{
var tasks = new List<Task>();
foreach (KeyValuePair<SelectQueryName, SelectQuery> select in SelectQueryes)
{
tasks.Add(Task.Run(() => machine.SetWMIProperties(select.Key, SelectFromWMI(select.Value, scope))));
}
await Task.WhenAll(tasks);
}
catch (Exception ex)
{
EventNotifier.LogOnScreen(string.Format("{0}, viz: {1}", ErrorList.GetEIbyID(15).definition, ex.Message));
EventNotifier.Log(ex, ErrorList.GetEIbyID(15));
}
}
catch (Exception ex)
{
EventNotifier.LogOnScreen(string.Format("{0}, viz: {1}", ErrorList.GetEIbyID(16).definition, ex.Message));
EventNotifier.Log(ex, ErrorList.GetEIbyID(17));
}
}
要等待LoadMachineData()
完成,可以将其签名更改为async Task
并以LoadMachineData().Wait()
调用.那是您需要的吗?
To wait for completion of LoadMachineData()
you can change it signature to async Task
and call as LoadMachineData().Wait()
. Is that what you need?
这篇关于创建到WMI的异步选择并等待其完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!