C#forms程序中的白屏

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

我目前正在开发一些跟踪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;
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
    {
    }
}