2012-09-09 107 views
1

我正在尝试用不同的方式在WinRT中完成游戏图形,如果我的测试应用程序可以测量并显示自己的CPU使用率,那么我可以比较不同的方法(ItemsControl与手动移动图像vs vs DirectX)。有没有办法让WinRT应用程序测量自己的CPU使用率?

在完全成熟的.NET中,我可以在两个已知时间点读取Process.TotalProcessorTime,然后将增量处理器时间除以增量时间(根据需要调整处理器数量)。如果应用程序以完全信任的方式运行,我甚至可以找到dwm.exe的Process实例(因为它完成了将GUI放在屏幕上的所有繁重工作)并将其添加到我的CPU时间中。这是我在我的Game Graphics test suite的WinForms和WPF版本中采用的方法。

但是在WinRT中,System.Diagnostics.Process类不存在。如果有一个替代API,我不确定在哪里寻找它。

我可以打开任务管理器并将其设置为保持最佳状态,并在应用程序运行时随时关注它。这并不理想,因为(a)它覆盖了我窗口的一部分,因此可能略微扭曲了结果;和(b)我不能做任何我自己的聚合或记录结果(例如“这是十秒钟内平均CPU使用率”)。因此,如果有某种方式可以以编程方式获得我的CPU使用率,那么我更喜欢这一点,只是因为它给了我更多的灵活性。

有什么办法让WinRT应用程序确定自己的CPU使用率?

回答

1

我不知道任何“已批准”API从Windows应用商店应用中获取此信息。

但是,如果您只想在测试应用程序中执行此操作,则可以使用“未经批准”的API。如果您使用未经批准的API,您的程序将无法通过WACK认证,并且无法上传到商店,但在本地进行测试即可。请注意,调用未经批准的API时没有保证,因此行为在形式上是未定义的,但许多函数都可以正常工作 - 至少在当前版本中。

我演示了如何在我今年夏天写的文章"printf debugging in Metro style apps"中的文章中调用AllocConsole。你可以用C#做​​类似的事情,或者使用P/Invoke来调用本地函数,或者编写一个可以从C#调用的C++ Windows运行时组件。

对于您的情况,我建议调用GetCurrentProcess来获取当前进程的句柄并将其传递到GetProcessTimes以获取用户和内核时间。我使用这种方法进行了简短的测试并获得了合理的结果。

下面是一个使用P/Invoke来拨打电话一个完整的C#类:

static class DebugProcessTimes 
{ 
    [StructLayout(LayoutKind.Sequential)] 
    private struct FileTime 
    { 
     public UInt32 Low; 
     public UInt32 High; 
    } 

    private static UInt64 ToUInt64(FileTime time) 
    { 
     return ((UInt64)time.High << 32) + time.Low; 
    } 

    [DllImport("kernel32.dll")] 
    private static extern IntPtr GetCurrentProcess(); 

    [DllImport("kernel32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool GetProcessTimes(
     IntPtr hProcess, 
     out FileTime lpCreationTime, 
     out FileTime lpExitTime, 
     out FileTime lpKernelTime, 
     out FileTime lpUserTime); 

    public struct ProcessTimes 
    { 
     public UInt64 CreationTime; 
     public UInt64 ExitTime; 
     public UInt64 KernelTime; 
     public UInt64 UserTime; 
    } 

    public static ProcessTimes GetProcessTimes() 
    { 
     FileTime creation, exit, kernel, user; 

     if (!GetProcessTimes(GetCurrentProcess(), 
       out creation, out exit, out kernel, out user)) 
      throw new Exception(":'("); 

     return new ProcessTimes 
     { 
      CreationTime = ToUInt64(creation), 
      ExitTime  = ToUInt64(exit), 
      KernelTime = ToUInt64(kernel), 
      UserTime  = ToUInt64(user) 
     }; 
    } 
} 

用法:

var times = DebugProcessTimes.GetProcessTimes(); 
+0

有趣!由于pinvoke.net上的声明依赖于类似于System.Runtime.InteropServices.FILETIME的类型,这些类型在WinRT中没有公开,所以你介意发布你的P/Invoke代码,因为它听起来像你已经困惑了? –

+0

我没有写过P/Invoke代码,但是我迅速地试了一下。查看更新。结果看起来很合理。 –

相关问题