gpt4 book ai didi

c# - Windows 窗体应用程序中的多线程调用?

转载 作者:太空狗 更新时间:2023-10-29 21:31:14 27 4
gpt4 key购买 nike

我试图让我的 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;
}

最佳答案

查看 Jon Skeet 关于多线程的文章,特别是关于 multi-threading winforms 的页面.它应该可以立即修复您。

基本上您需要检查是否需要调用,然后在需要时执行调用。阅读本文后,您应该能够将 UI 更新代码重构为如下所示的 block :

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();
}

在您的代码中,将需要调用,因为您使用的是计时器。根据 System.Timers.Timer 的文档:

The Elapsed event is raised on a ThreadPool thread.

这意味着您设置为 Timer 的委托(delegate)的 OnTimedEvent() 方法将在下一个可用的 ThreadPool 线程上执行,该线程肯定不是您的 UI 线程。该文档还提出了解决此问题的替代方法:

If you use the Timer with a user interface element, such as a form or control, assign the form or control that contains the Timer to the SynchronizingObject property, so that the event is marshaled to the user interface thread.

您可能会发现这条路线更容易,但我还没有尝试过。

关于c# - Windows 窗体应用程序中的多线程调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2352987/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com