2012-04-06 85 views
0

好吧,我在我的程序中有一个计算CPU使用率的性能计数器。它工作得很好,没有错误等等。但是!只要性能计数器加载,我的UI就会冻结。C#Performancecounter冻结用户界面

我加载的PerformanceCounter在BackgroundWorker的,所以我不知道为什么它冻结UI做...

任何想法?如果是这样,谢谢!

代码

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
    { 
     try 
     { 
      SetPerformanceCounters(); 
      timerUpdateGUIControls.Start(); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex); 
     } 
    } 

    private void SetPerformanceCounters() 
    { 
     performanceCounterCPU.CounterName = "% Processor Time"; 
     performanceCounterCPU.CategoryName = "Processor"; 
     performanceCounterCPU.InstanceName = "_Total"; 

     performanceCounterRAM.CounterName = "% Committed Bytes In Use"; 
     performanceCounterRAM.CategoryName = "Memory"; 
    } 
    private void timerUpdateGUIControls_Tick(object sender, EventArgs e) 
    { 
     try 
     { 
      SystemStatusprogressbarCPU.Value = (int)(performanceCounterCPU.NextValue()); 
      SystemStatuslabelCPU.Text = "CPU: " + SystemStatusprogressbarCPU.Value.ToString(CultureInfo.InvariantCulture) + "%"; 

      var phav = PerformanceInfo.GetPhysicalAvailableMemoryInMiB(); 
      var tot = PerformanceInfo.GetTotalMemoryInMiB(); 
      var percentFree = ((decimal)phav/tot) * 100; 
      var percentOccupied = 100 - percentFree; 
      SystemStatuslabelRAM.Text = "RAM: " + (percentOccupied.ToString(CultureInfo.InvariantCulture) + "%").Remove(2, 28); 
      SystemStatusprogressbarRAM.Value = Convert.ToInt32((percentOccupied)); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex); 
     } 
    } 

是可以获得RAM价值的东西类:

public static class PerformanceInfo 
{ 
    [DllImport("psapi.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    public static extern bool GetPerformanceInfo([Out] out PerformanceInformation PerformanceInformation, 
               [In] int Size); 

    [StructLayout(LayoutKind.Sequential)] 
    public struct PerformanceInformation 
    { 
     public int Size; 
     public IntPtr CommitTotal; 
     public IntPtr CommitLimit; 
     public IntPtr CommitPeak; 
     public IntPtr PhysicalTotal; 
     public IntPtr PhysicalAvailable; 
     public IntPtr SystemCache; 
     public IntPtr KernelTotal; 
     public IntPtr KernelPaged; 
     public IntPtr KernelNonPaged; 
     public IntPtr PageSize; 
     public int HandlesCount; 
     public int ProcessCount; 
     public int ThreadCount; 
    } 

    public static Int64 GetPhysicalAvailableMemoryInMiB() 
    { 
     var pi = new PerformanceInformation(); 
     if (GetPerformanceInfo(out pi, Marshal.SizeOf(pi))) 
     { 
      return Convert.ToInt64((pi.PhysicalAvailable.ToInt64() * pi.PageSize.ToInt64()/1048576)); 
     } 
     return -1; 
    } 

    public static Int64 GetTotalMemoryInMiB() 
    { 
     var pi = new PerformanceInformation(); 
     if (GetPerformanceInfo(out pi, Marshal.SizeOf(pi))) 
     { 
      return Convert.ToInt64((pi.PhysicalTotal.ToInt64() * pi.PageSize.ToInt64()/1048576)); 
     } 
     return -1; 
    } 
} 
+1

一些代码,将有助于... – RvdK 2012-04-06 11:28:19

+0

@PoweRoy哦啊,对不起。添加了代码。 – 2012-04-06 11:32:41

回答

2

在新建的BackgroundWorker的DoWork的性能计数器。但这只是创造,而不是实际的工作。你应该将内容从timerUpdateGUIControls_Tick移动到backgroundWorker1_DoWork

struct SystemStatus 
{ 
    public int CpuLoad; 
    public decimal OccupiedPercentage; 
} 

private void SetPerformanceCounters() 
{ 
    performanceCounterCPU.CounterName = "% Processor Time"; 
    performanceCounterCPU.CategoryName = "Processor"; 
    performanceCounterCPU.InstanceName = "_Total"; 

    performanceCounterRAM.CounterName = "% Committed Bytes In Use"; 
    performanceCounterRAM.CategoryName = "Memory"; 
} 

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    try 
    { 
     SetPerformanceCounters();  

     while (!backgroundWorker1.CancellationPending) 
     { 
      SystemStatus status = new SystemStatus(); 
      status.CpuLoad = (int)(performanceCounterCPU.NextValue())  

      var phav = PerformanceInfo.GetPhysicalAvailableMemoryInMiB(); 
      var tot = PerformanceInfo.GetTotalMemoryInMiB(); 
      var percentFree = ((decimal)phav/tot) * 100; 
      status.OccupiedPercentage = 100 - percentFree; 

      backgroundWorker1.ReportProgress(0, status); 

      Thread.Sleep(500); //set update frequency to 500ms 
     } 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex); 
    } 
} 

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    SystemStatus status = e.UserState as SystemStatus; 

    SystemStatusprogressbarCPU.Value = status.CpuLoad; 
    SystemStatuslabelCPU.Text = "CPU: " + Sstatus.CpuLoad.ToString(CultureInfo.InvariantCulture) + "%"; 

    SystemStatuslabelRAM.Text = "RAM: " + (status.OccupiedPercentage.ToString(CultureInfo.InvariantCulture) + "%").Remove(2, 28); 
    SystemStatusprogressbarRAM.Value = Convert.ToInt32(status.OccupiedPercentage); 
} 

不要忘了给ProgressChanged功能添加到backgroundworker1:

backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); 
+0

但是,如果在backgruondworker中每500毫秒如何更新'timerUpdateGUIControls_Tick'的内容? – 2012-04-06 11:38:04

+0

Thread.Sleep会做。 – RvdK 2012-04-06 11:40:22

+0

Okai,我试图用这个更新标签和进度条交叉线程:'Invoke((MethodInvoker) delegate {/ * code * /});'但它仍然会*冻结用户界面。 (假设它现在变成白色:o)。 – 2012-04-06 11:44:55