C#forms程序中的白屏
我目前正在开发一些跟踪CPU使用情况的工具,但当我启动从CPU中提取数据的线程时,屏幕上一片空白,好像我启动了一个新的程序C#forms程序中的白屏,c#,multithreading,C#,Multithreading,我目前正在开发一些跟踪CPU使用情况的工具,但当我启动从CPU中提取数据的线程时,屏幕上一片空白,好像我启动了一个新的程序 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; us
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Management.Instrumentation;
using System.Management;
using System.Collections.Specialized;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
Thread cpuData;
public Form1()
{
cpuData = new Thread(new ThreadStart(cpuDataThread));
cpuData.Start();
}
public void cpuDataThread()
{
ulong i;
i = 0;
try
{
ManagementClass cpuDataClass = new ManagementClass("Win32_PerfFormattedData_PerfOS_Processor");
while (true)
{
ManagementObjectCollection cpuDataClassCollection = cpuDataClass.GetInstances();
foreach (ManagementObject obj in cpuDataClassCollection)
{
if (obj["Name"].ToString() == "_Total")
{
i = Convert.ToUInt64(obj["C1TransitionsPersec"]);
}
}
Thread.Sleep(100);
}
}
catch (ThreadAbortException tbe)
{
}
progressBar1.Maximum = 100;
progressBar1.Minimum = 1;
progressBar1.Value = (int)i;
}
}
}
这只是我为个人使用编写的一个程序,但我想让它工作,进度条也不工作。我也想得到一些帮助。您可能还需要为线程提供以下属性(启动前方法): 接下来是第二个问题(progressbar)。如果要将数据传递到UI,则需要使用Dispatcher,如下所示:
Dispatcher.Invoke((Action)delegate() { /* update UI */ });
我对您的代码做了一些修改,似乎很有效: 您使用的是Win表单,我也是。我使用的不是手动线程,而是Backgroundworker(“bkwCpuLoad”) 为了适应这些值,我将最大值设置为10000:
private void Form1_Load(object sender, EventArgs e)
{
progressBar1.Maximum = 10000;
progressBar1.Minimum = 0;
bkwCpuLoad.RunWorkerAsync();
}
private void bkwCpuLoad_DoWork(object sender, DoWorkEventArgs e)
{
ulong i;
i = 0;
try
{
ManagementClass cpuDataClass = new ManagementClass("Win32_PerfFormattedData_PerfOS_Processor");
while (true)
{
ManagementObjectCollection cpuDataClassCollection = cpuDataClass.GetInstances();
foreach (ManagementObject obj in cpuDataClassCollection)
{
if (obj["Name"].ToString() == "_Total")
{
i = Convert.ToUInt64(obj["C1TransitionsPersec"]);
}
bkwCpuLoad.ReportProgress((int)i);
}
Thread.Sleep(100);
}
}
catch (ThreadAbortException tbe)
{
}
}
private void bkwCpuLoad_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var perc = e.ProgressPercentage;
if (perc > progressBar1.Maximum)
perc = progressBar1.Maximum;
progressBar1.Value = perc;
try
{
progressBar1.Value--;
progressBar1.Value++;
}
catch
{
}
}
progressBar1.Value--
,progressBar1.Value++bit
:在像您这样的情况下,有一件事非常不理想,那就是progressbar动画,它太慢了。但是:如果减少progressbar值,则它不会设置动画,而是直接绘制。
因此,设置该值(动画开始),将其减少1(直接跳到值),再次增加该值会使progressbar的速度更快 您的构造函数没有调用
InitializeComponent()
这是WinForms designer创建的方法。这会在我关闭窗口的那一刻崩溃+它无法解决它的崩溃,因为你试图在没有使用Dispatcher的情况下从第二个线程调用UI。就像@Equalsk所说的-你创建了一个无限循环。无限循环在技术上并不坏,这是一种让线程保持活动状态的常见方法,我假设他正在这样做,但我想检查一下,因为这是死锁的常见原因。我会使用后台工作程序
,将其Reports proges
属性设置为true,并将progressbar更新放在ProgressChanged事件中。你能澄清一下空白是什么意思吗?程序完全消失,变成白色,好像UI线程被锁定,或者看起来您没有窗体控件?我看不出你从哪里打破了你的while循环,它是否意味着永远像那样运行?是的,还有这个循环。我没有注意到它需要永远运行,它应该每.1秒获取一次cpu使用率,它看起来很像是你启动了一个新项目,并在不修改它的情况下运行它,所以只是为了达到100%,你说如果你注释掉这行代码来启动线程,就像这样//cpuData.start()代码>程序看起来很好,并且所有控件都处于打开状态,如进度条。如果你接着启动线程,所有这些东西都消失了,看起来像是一个全新的空表单?你的代码结构很差。它只会更新屏幕一次(或尝试更新并失败),但只有在抛出异常以中断无限循环时才会更新。回到前面不要忘记,要使用此示例,您需要将BackGroundWorker
从工具箱的组件部分拖动到您的项目上。OP应该查看关于使用backgroundworkers的更多信息。这似乎可行,但我无法显示cpu利用率数据,我需要以任何方式启动该脚本吗?您希望在表单上的什么时间点和什么位置显示什么?基本上是实时cpu负载,在未来的ram负载中,对于cpu负载,您可能需要PercentProcessorTime
而不是c1transitionpersec
。请看这里:。另外,请查看以下内容:
private void Form1_Load(object sender, EventArgs e)
{
progressBar1.Maximum = 10000;
progressBar1.Minimum = 0;
bkwCpuLoad.RunWorkerAsync();
}
private void bkwCpuLoad_DoWork(object sender, DoWorkEventArgs e)
{
ulong i;
i = 0;
try
{
ManagementClass cpuDataClass = new ManagementClass("Win32_PerfFormattedData_PerfOS_Processor");
while (true)
{
ManagementObjectCollection cpuDataClassCollection = cpuDataClass.GetInstances();
foreach (ManagementObject obj in cpuDataClassCollection)
{
if (obj["Name"].ToString() == "_Total")
{
i = Convert.ToUInt64(obj["C1TransitionsPersec"]);
}
bkwCpuLoad.ReportProgress((int)i);
}
Thread.Sleep(100);
}
}
catch (ThreadAbortException tbe)
{
}
}
private void bkwCpuLoad_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var perc = e.ProgressPercentage;
if (perc > progressBar1.Maximum)
perc = progressBar1.Maximum;
progressBar1.Value = perc;
try
{
progressBar1.Value--;
progressBar1.Value++;
}
catch
{
}
}