C# 为什么有时我会得到异常索引?
这是一个计时器滴答事件,我正在获取每个进程的内存使用情况。 在95%的时间里,甚至更多的时候,它工作得很好。我试了20次运行我的程序,直到异常抛出 在表格顶部:C# 为什么有时我会得到异常索引?,c#,.net,winforms,C#,.net,Winforms,这是一个计时器滴答事件,我正在获取每个进程的内存使用情况。 在95%的时间里,甚至更多的时候,它工作得很好。我试了20次运行我的程序,直到异常抛出 在表格顶部: System.Timers.Timer aTimer = new System.Timers.Timer(); 然后在构造函数中: aTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent); aTimer.Interval = 1000; 然后,计时器
System.Timers.Timer aTimer = new System.Timers.Timer();
然后在构造函数中:
aTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 1000;
然后,计时器已过事件:
Image ima = null;
private void OnTimedEvent(object source, System.Timers.ElapsedEventArgs e)
{
List<MyProgress> prog = new List<MyProgress>();
prog = new List<MyProgress>();
DoubleBufferedd(dataGridView1, true);
procList = Process.GetProcesses().ToList();
for (int i = 0; i < procList.Count; i++)
{
Process[] processes = Process.GetProcessesByName(procList[i].ProcessName);
PerformanceCounter performanceCounter = new PerformanceCounter();
performanceCounter.CategoryName = "Process";
performanceCounter.CounterName = "Working Set - Private";
performanceCounter.InstanceName = processes[0].ProcessName;
try
{
var icon = Icon.ExtractAssociatedIcon(processes[0].MainModule.FileName);
ima = icon.ToBitmap();
ima = resizeImage(ima, new Size(25, 25));
ima = (Image)(new Bitmap(ima, new Size(25, 25)));
}
catch
{
}
prog.Add(new MyProgress { Id = procList[i].Id, Progress = ((uint)performanceCounter.NextValue() / 1024).ToString("N0"), ProcImage = ima, ProcessName = procList[i].ProcessName });
}
BeginInvoke((Action)(() =>
{
List<MyProgress> list = prog;//new List<MyProgress>();
foreach (MyProgress p in list)
{
DataGridViewRow row;
if (!processRows.TryGetValue(p.Id, out row))
{
int index = dataGridView1.Rows.Add(p.ProcImage, p.ProcessName, null, p.Progress);
row = dataGridView1.Rows[index];
processRows.Add(p.Id, row);
}
else
{
row.Cells[3].Value = p.Progress;
}
}
foreach (int id in processRows.Keys.Except(list.Select(p => p.Id)).ToArray())
{
dataGridView1.Rows.Remove(processRows[id]);
processRows.Remove(id);
}
}));
}
中发生“System.IndexOutOfRangeException”类型的异常
Automation.exe,但未在用户代码中处理
附加信息:索引超出了数组的边界
用户代码未处理System.IndexOutOfRangeException
它只会发生一次或多次。大多数情况下,异常未显示
当我将鼠标放在proclist上时,我看到计数:
Count=函数计算已禁用,因为上一个函数
评估超时。必须继续执行才能重新启用函数
评估
计时器的间隔设置为1000ms
不确定这意味着什么,我必须继续执行以重新启用函数求值。以及如何修复它。
为什么有时候它会做出例外,而在大多数情况下不会
我根据Dan answer更改了代码,但现在在另一个地方出现异常。
这是新代码:
Image ima = null;
private void OnTimedEvent(object source, System.Timers.ElapsedEventArgs e)
{
List<MyProgress> prog = new List<MyProgress>();
prog = new List<MyProgress>();
DoubleBufferedd(dataGridView1, true);
procList = Process.GetProcesses().ToList();
for (int i = 0; i < procList.Count; i++)
{
PerformanceCounter performanceCounter = new PerformanceCounter();
performanceCounter.CategoryName = "Process";
performanceCounter.CounterName = "Working Set - Private";//"Working Set";
performanceCounter.InstanceName = procList[i].ProcessName;
try
{
var icon = Icon.ExtractAssociatedIcon(procList[i].MainModule.FileName);
ima = icon.ToBitmap();
ima = resizeImage(ima, new Size(25, 25));
ima = (Image)(new Bitmap(ima, new Size(25, 25)));
}
catch
{
}
prog.Add(new MyProgress { Id = procList[i].Id, Progress = ((uint)performanceCounter.NextValue() / 1024).ToString("N0"), ProcImage = ima, ProcessName = procList[i].ProcessName });
}
BeginInvoke((Action)(() =>
{
List<MyProgress> list = prog;
foreach (MyProgress p in list)
{
DataGridViewRow row;
if (!processRows.TryGetValue(p.Id, out row))
{
int index = dataGridView1.Rows.Add(p.ProcImage, p.ProcessName, null, p.Progress);
row = dataGridView1.Rows[index];
processRows.Add(p.Id, row);
}
else
{
row.Cells[3].Value = p.Progress;
}
}
foreach (int id in processRows.Keys.Except(list.Select(p => p.Id)).ToArray())
{
dataGridView1.Rows.Remove(processRows[id]);
processRows.Remove(id);
}
}));
}
这一行我也在使用procList[i]
performanceCounter.InstanceName = procList[i].ProcessName;
var icon = Icon.ExtractAssociatedIcon(procList[i].MainModule.FileName);
但现在我在网上遇到了一个例外:
performanceCounter.InstanceName = processes[0].ProcessName;
prog.Add(new MyProgress { Id = procList[i].Id, Progress = ((uint)performanceCounter.NextValue() / 1024).ToString("N0"), ProcImage = ima, ProcessName = procList[i].ProcessName });
无效操作例外
System.dll中发生“System.InvalidOperationException”类型的异常,但未在用户代码中处理
其他信息:指定类别中不存在实例“SearchFilterHost”
System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=Instance 'SearchFilterHost' does not exist in the specified Category.
Source=System
StackTrace:
at System.Diagnostics.CounterDefinitionSample.GetInstanceValue(String instanceName)
at System.Diagnostics.PerformanceCounter.NextSample()
at System.Diagnostics.PerformanceCounter.NextValue()
at Automation.Form1.OnTimedEvent(Object source, ElapsedEventArgs e) in d:\C-Sharp\Automation\Automation\Automation\Form1.cs:line 805
at System.Timers.Timer.MyTimerCallback(Object state)
InnerException:
可能没有具有您要查找的名称的进程。当这种情况发生时,进程的长度将为0,并且没有有效的索引。所以,无论你在括号里放了什么数字,你都会得到一个IndexOutOfRangeException 要解决此问题,在使用进程数组之前,应确保存在匹配的进程:
实现这一目标还有很多其他方法,但这应该为您指明正确的方向。以下是与您的问题相关的三行重要代码:
procList = Process.GetProcesses().ToList();
Process[] processes = Process.GetProcessesByName(procList[i].ProcessName);
performanceCounter.InstanceName = processes[0].ProcessName;
你在这里做的是
获取所有进程的列表
获取与第一个列表中的一个进程同名的进程列表
获取第二个列表中第一个进程的名称
忽略这里的冗余,问题在于时间
假设您有一个正在运行的进程foo.exe。该过程出现在步骤1的列表中。如果该过程在步骤1和步骤2之间终止,则步骤2中foo.exe的列表将为空。当列表为空时调用进程[0]将引发您看到的异常
为了避免这种情况,我建议您完全避免第2步:您已经检索了所有进程的信息,所以请使用您已经拥有的数据。这将有可能加快您的代码的好处 在循环过程中,如果进程结束,将引发异常…您可能遇到线程问题。您可以使用来更好地了解发生了什么。GetProcessByName可能返回空数组,索引0超出范围。不要假设进程[0]存在,您将不会获得异常。当您超出数组的边界时,会发生IndexOutOfRangeException。例如,如果您有一个包含3个对象的数组,并且尝试调用ArrayName[4],则会出现该错误。设置断点并找出代码不工作的原因。数组是否已满?不,那么它将超出数组的边界。Dan我更改了代码,删除了第2步中的Process[]processs行,现在不使用它。接下来的两行中,instancename=I did procList[I].ProcessName的行和extract procList[I]图标的行.MainModule.FileName但现在我遇到了另一个异常。Dan我也用我所做的更改和现在遇到的异常更新了我的问题。@ManuelSpechia:您的更新更改了问题的含义/内容,使现有答案不再相关。您应该恢复编辑以保留现有问题,然后将新问题作为单独问题发布。不过,作为解决新问题的建议:打破这条界线。您正在调用多个方法,但不清楚是哪个方法引发了异常,因此使用额外的局部变量在单独的行上调用每个方法来存储结果,您可以缩小问题的范围。
procList = Process.GetProcesses().ToList();
Process[] processes = Process.GetProcessesByName(procList[i].ProcessName);
performanceCounter.InstanceName = processes[0].ProcessName;