有没有办法让WinRT应用程序测量自己的CPU使用率?

时间:2012-09-09 12:12:36

标签: windows-runtime cpu-usage

我正在尝试使用不同的方法在WinRT中制作游戏图形,如果我的测试应用程序可以测量并显示自己的CPU使用情况,那就太好了,所以我可以比较不同的方法(ItemsControl与手动移动图像)与DirectX)。

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

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

我可以打开任务管理器并将其设置为保持最佳状态,并在我的应用运行时随时关注它。这不太理想,因为(a)它覆盖了我的窗户的一部分,因此可能会略微扭曲结果; (b)我无法进行任何自己的聚合或记录结果(例如“这里是10秒范围内的平均CPU使用率”)。因此,如果有一些方法可以通过编程方式获得我的CPU使用率,我更喜欢这样,只是因为它给了我更多的灵活性。

WinRT应用有没有办法确定自己的CPU使用率?

2 个答案:

答案 0 :(得分:1)

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

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

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

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

这是一个完整的C#类,它使用P / Invoke进行调用:

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();

答案 1 :(得分:0)

不幸的是,WinRT中没有相应的System.Diagnostics.Process类,至少目前没有(Missing reference to System.Diagnostics.ProcessAccessing other processes in Win8 Metro-style app)。一些本机API暴露给WinRT(例如,请参阅How can I get the number of logical CPUs on WinRT?),但我找不到列表。