Waf*_*les 6 c# multithreading process performancecounter winforms
我试图使我的C#应用程序多线程,因为有时,我得到一个异常,说我已经以不安全的方式调用了一个线程.我以前从未在程序中做过任何多线程,所以如果我对这个问题听起来有点无知,请耐心等待.
我的程序概述是我想要进行性能监视应用程序.这需要使用C#中的进程和性能计数器类来启动和监视应用程序的处理器时间,并将该数字发送回UI.但是,在实际调用性能计数器的nextValue方法(由于计时器设置为每秒执行一次)的方法中,我有时会得到上述异常,它会以不安全的方式调用线程.
我附上了一些代码供你细读.我知道这是一个耗时的问题,所以如果有人能为我提供任何关于在哪里制作新线程以及如何以安全的方式调用它的话,我将非常感激.我试着看看MSDN上的内容,但这有点让我感到困惑.
private void runBtn_Click(object sender, EventArgs e)
{
// this is called when the user tells the program to launch the desired program and
// monitor it's CPU usage.
// sets up the process and performance counter
m.runAndMonitorApplication();
// Create a new timer that runs every second, and gets CPU readings.
crntTimer = new System.Timers.Timer();
crntTimer.Interval = 1000;
crntTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
crntTimer.Enabled = true;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
// get the current processor time reading
float cpuReading = m.getCPUValue();
// update the current cpu label
crntreadingslbl.Text = cpuReading.ToString(); //
}
// runs the application
public void runAndMonitorApplication()
{
p = new Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = fileName;
p.Start();
pc = new System.Diagnostics.PerformanceCounter("Process",
"% Processor Time",
p.ProcessName,
true);
}
// This returns the current percentage of CPU utilization for the process
public float getCPUValue()
{
float usage = pc.NextValue();
return usage;
}
Run Code Online (Sandbox Code Playgroud)
查看Jon Skeet关于多线程的文章,特别是关于多线程winforms的页面.它应该能解决你的问题.
基本上,您需要检查是否需要调用,然后根据需要执行调用.阅读完本文后,您应该能够将UI更新代码重构为如下所示的块:
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
// get the current processor time reading
float cpuReading = m.getCPUValue();
if (InvokeRequired)
{
// We're not in the UI thread, so we need to call BeginInvoke
BeginInvoke(new Action(() => crntreadingslbl.Text = cpuReading.ToString()));
return;
}
// Must be on the UI thread if we've got this far
crntreadingslbl.Text = cpuReading.ToString();
}
Run Code Online (Sandbox Code Playgroud)
在您的代码中,因为您使用的是Timer,所以需要进行调用.根据System.Timers.Timer的文档:
在ThreadPool线程上引发Elapsed事件.
这意味着您设置为Timer的委托的OnTimedEvent()方法将在下一个可用的ThreadPool线程上执行,该线程肯定不是您的UI线程.该文档还建议了另一种解决此问题的方法:
如果将Timer与用户界面元素(如窗体或控件)一起使用,请将包含Timer的窗体或控件分配给 SynchronizingObject 属性,以便将事件封送到用户界面线程.
您可能会发现这条路线更容易,但我还没有尝试过.
| 归档时间: |
|
| 查看次数: |
13085 次 |
| 最近记录: |