我想知道是否有人对我在下面的代码中遇到的问题有任何指导。代码的目的是:
我遇到的问题是连接到大约1000台计算机后,主GUI应用程序锁定。为了避免明显的GUI锁定我一直在使用Invoke()来更新主GUI。
这个错误很难在测试环境中重现,因为它在连接到如此多的计算机之后发生。我对这个bug的想法是它可能是以下之一(我不是专家):
以下是代码,它以 ScanButton_Click()开头:
namespace WMIScan
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
// ...Other code removed as it is irrelevant
private void ScanButton_Click(object sender, EventArgs e)
{
/*
* Scan all computers in the list
*/
List<string> computers = new List<string>();
foreach (ListViewItem item in CompList1.Items)
{
computers.Add(item.Text);
item.SubItems[1].Text = "";
item.SubItems[2].Text = "";
item.SubItems[3].Text = "";
}
LaunchScanning(computers);
}
private void LaunchScanning(List<string> computers)
{
/*
* This function is responsible for launching a scan against all computers in the list
* It handles the multithreading of scan jobs.
*/
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Value = 0;
toolStripProgressBar1.Maximum = computers.Count;
System.Threading.Tasks.Task Processing;
//Support the scanning of multiple computers.
toolStripStatusLabel1.Text = "Scanning of " + computers.Count + " computers(s) started at: " + DateTime.Now;
Processing = Task.Factory.StartNew(() =>
{
Parallel.ForEach(computers, new ParallelOptions { MaxDegreeOfParallelism = max_threads }, computer =>
{
BeginScanning(computer);
toolStripProgressBar1.GetCurrentParent().BeginInvoke(new MethodInvoker(delegate { toolStripProgressBar1.Value++; }));
});
toolStripStatusLabel1.Text = "Scanning of " + computers.Count + " computers(s) completed.";
}
);
}
private void BeginScanning(string computer)
{
/*
* This function is responsible for conducting the scanning of a single computer
*/
ManagementScope cimv2_scope = new ManagementScope();
ConnectionOptions options = new ConnectionOptions();
ObjectQuery query;
ManagementObjectSearcher searcher;
ManagementObjectCollection queryCollection;
System.IO.StreamWriter file = null;
string completed_jobs = "";
string errors = "";
string[] listview_output = { "", "","" };
//Check if credentials have been provided.
if (username != "" && password != "")
{
options.Username = username;
options.Password = password;
}
//Attempt inital connection
cimv2_scope = new ManagementScope(@"\\" + computer + @"\root\CIMV2", options);
try
{
//Create new scope connections
cimv2_scope.Connect();
//Attempt to open output file.
try
{
file = new System.IO.StreamWriter(output_dir + @"\" + computer + ".txt");
file.WriteLine("######Start " + DateTime.Now);
//Query Operating System
try
{
query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
searcher = new ManagementObjectSearcher(cimv2_scope, query);
queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
DateTime InstallDate = ManagementDateTimeConverter.ToDateTime(m["InstallDate"].ToString());
DateTime LastBootUpTime = ManagementDateTimeConverter.ToDateTime(m["LastBootUpTime"].ToString());
DateTime LocalDateTime = ManagementDateTimeConverter.ToDateTime(m["LocalDateTime"].ToString());
file.WriteLine("OS," + computer + "," + m["CSName"] + "," + m["BuildNumber"] + "," + m["Caption"]
+ "," + m["Version"] + "," + m["OSArchitecture"] + "," + m["ServicePackMajorVersion"] + ","
+ m["ServicePackMinorVersion"] + "," + m["CurrentTimeZone"] + "," + InstallDate + "," +
LastBootUpTime + "," + LocalDateTime + "," + m["OSLanguage"] + "," + m["OSProductSuite"] +
"," + m["OSType"] + "," + m["RegisteredUser"] + "," + m["SerialNumber"] + "," + m["SystemDevice"]
+ "," + m["SystemDirectory"] + "," + m["SystemDrive"] + "," + m["WindowsDirectory"]);
}
completed_jobs = "OS";
}
catch (Exception e)
{
errors += ("[Operating System] " + e.Message);
}
// ... Many more WMI queries here
//Processing completed
file.WriteLine("Completed " + DateTime.Now);
file.Close();
CompList1.BeginInvoke(new MethodInvoker(delegate
{
ListViewItem tmp = CompList1.FindItemWithText(computer);
tmp.SubItems[1].Text = "True";
tmp.SubItems[2].Text = completed_jobs;
tmp.SubItems[3].Text = errors;
}));
}
catch (Exception e) //File Open Error
{
CompList1.BeginInvoke(new MethodInvoker(delegate
{
ListViewItem tmp = CompList1.FindItemWithText(computer);
tmp.SubItems[1].Text = "Failed";
tmp.SubItems[2].Text = "";
tmp.SubItems[3].Text = e.Message;
}));
}
}
catch (Exception e) //Scope Connection Error
{
CompList1.BeginInvoke(new MethodInvoker(delegate
{
ListViewItem tmp = CompList1.FindItemWithText(computer);
tmp.SubItems[1].Text = "Failed";
tmp.SubItems[2].Text = "";
tmp.SubItems[3].Text = e.Message;
}));
}
}
}
}
&#13;
我是C#和StackOverflow的新手,非常感谢任何帮助!
谢谢,
乔丝
答案 0 :(得分:-1)
据我所知,Parallel.ForEach与你拥有的核心数量有关。即。如果你有4个核心,你将能够并行处理4个线程。
为什么不做foreach并为您希望处理的每个操作创建一个Task。 (我没有对此进行过测试,但你明白了这一点)
var tasks = new List<Task>();
foreach(var computer in computers)
{
var t =Task.Factory.StartNew(() =>
{
BeginScanning(computer);
Acttion myUiStuff = () =>
{
toolStripProgressBar1.Value++;
toolStripStatusLabel1.Text = "Scanning of " + computers.Count + " computers(s) completed.";
};
//im assuming you are using WinForms; UI objects must be modified by UI thread so thats is the call to BeginInvoke; If its WPF call the Dispatcher.
BeginInvoke(myUiStuff);
}
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray());