通过计时器更新标签时C#GUI冻结

时间:2014-02-10 15:27:03

标签: c# user-interface timer visual-studio-2013 freeze

我有一个非常简单的C#程序(.net 4.5,VS 2013),它使用Winforms运行以获取当前的CPU速度和最大CPU速度并更新以下标签: lblCPUMaxValue and lblCPUCurrentValue

lblCPUMaxValue
lblCPUCurrentValue

我创建了一个名为timerCPUstats的计时器,每隔3000ms计时并调用函数updatePerfInfo():

public uint CPUSpeed()
{
    ManagementObject Mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'");
    uint speed = (uint)(Mo["CurrentClockSpeed"]);
    Mo.Dispose();
    return speed;
}

public uint maxCPUSpeed()
{
    ManagementObject Mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'");
    uint speed = (uint)(Mo["MaxClockSpeed"]);
    Mo.Dispose();
    return speed;
} 

public string formatMhzGhz(uint mhz)
{
    decimal ghz = (decimal)mhz / 1000;
    ghz = Math.Round(ghz, 2);
    string stringGhz = ghz.ToString() + " GHz";
    return stringGhz;
}

public void updatePerfInfo()
{
    lblCPUMaxValue.Text = formatMhzGhz(maxCPUSpeed());
    lblCPUCurrentValue.Text = formatMhzGhz(CPUSpeed());
}

问题在于每次标签更新时程序会冻结几秒钟。它基本上变得非互动/冻结。有办法解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

您通过在UI线程中执行长时间运行的非UI工作来阻止UI线程。您需要将该工作卸载到另一个线程,然后使用该工作的结果更新UI。

BackgroundWorker专为此精确操作而设计。计算Result事件处理程序中的DoWork并设置该结果,然后使用Result事件处理程序将RunWorkerCompleted显示到UI。

另一个选项,如果您使用的是C#5.0,则使用await,可以让您写一下:

public async void updatePerfInfo()
{
    lblCPUMaxValue.Text = await Task.Run(()=>formatMhzGhz(maxCPUSpeed()));
    lblCPUCurrentValue.Text = await Task.Run(()=>formatMhzGhz(CPUSpeed()));
}