1

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

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

但在 WinRT 中,System.Diagnostics.Process 类不存在。如果有备用 API,我不确定在哪里可以找到它。

我可以打开任务管理器并将其设置为保持在顶部,并在我的应用程序运行时密切关注它。这不太理想,因为(a)它覆盖了我的窗口的一部分,因此可能会稍微扭曲结果;(b) 我不能对结果进行任何自己的聚合或记录(例如,“这是十秒内的平均 CPU 使用率”)。因此,如果有某种方法可以让我以编程方式获取 CPU 使用率,我更愿意这样做,因为它为我提供了额外的灵活性。

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

4

2 回答 2

1

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

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

AllocConsole我在今年夏天早些时候写的一篇文章“Metro 风格应用程序中的 printf 调试”中演示了如何调用。您可以在 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();
于 2012-09-09T14:04:34.917 回答
0

不幸的是,WinRT 中没有等效的 System.Diagnostics.Process 类,至少目前没有(缺少对 System.Diagnostics.Process 的引用在 Win8 Metro 风格的应用程序中访问其他进程)。一些本机 API 向 WinRT 公开(请参阅如何获取 WinRT 上的逻辑 CPU 数量?例如),但我找不到列表。

于 2012-09-09T12:27:04.303 回答