【问题标题】:How to get process memory from both .NET Standard 2.0 and UWP?如何从 .NET Standard 2.0 和 UWP 中获取进程内存?
【发布时间】:2018-07-15 07:57:18
【问题描述】:

我正在开发一个小型 .NET Standard 2.0 logging library,但我无法找到一种方法来可靠地获取当前进程在所有平台上使用的内存,尤其是在 UWP 上。

现在我正在使用这段代码(.NET Standard 2.0):

long memory = Process.GetCurrentProcess().PrivateMemorySize64;

效果很好,但是在 UWP 上抛出了一个很好的 PlatformNotSupportedException 异常(实际上,这只是在 DEBUG 模式下,而在 RELEASE 中直接抛出 TypeLoadException 加上一堆其他 P/出于某种原因调用异常)。

这里的问题是 UWP 显然不支持该 API,我应该在哪里使用:

long memory = (long)MemoryManager.AppMemoryUsage;

问题在于MemoryManager 是一个仅限 UWP 的 API,它在 .NET Standard 2.0 中不存在。现在,想到的第一个解决方法是在库中公开一个设置,让用户手动设置一个自定义的Func<long> 委托来检索当前的内存使用情况,这样如果它知道默认方法不适用于当前平台,可以覆盖它。

不过,这似乎是一个糟糕的技巧,我希望将所有内容都保留在库中。所以我的问题是:

有没有办法在任何支持 .NET Standard 2.0 库的平台上可靠地检索当前进程/应用程序的使用情况?

谢谢!

【问题讨论】:

    标签: c# .net uwp .net-standard .net-standard-2.0


    【解决方案1】:

    也许有点脏,但以下方法可以工作(可能会添加一些更好的错误处理等):

    public static long GetProcessMemory()
    {
        try
        {
            return Process.GetCurrentProcess().PrivateMemorySize64;
        }
        catch
        {           
            var type = Type.GetType("Windows.System.MemoryManager, Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime");
            return Convert.ToInt64(type.GetProperty("AppMemoryUsage", BindingFlags.Public | BindingFlags.Static).GetValue(null, null));
        }
    }
    

    我使用反射来解决以下事实:MemoryManager 在编译时不适用于 .NET Standard,但适用于 UWP 运行时。这样,相同的程序集将适用于两个运行时。
    但总的来说,我更喜欢像 Martin 建议的那样在每个运行时生成合适的程序集的方法。

    【讨论】:

    • 感谢您的建议,这确实是我最终使用的方法。您的解决方案不起作用(我不想通过在此处发布我自己的代码来“窃取”有效答案),如果您可以编辑您的解决方案,我很乐意将其标记为有效。您只需要更改类型名称(它需要完全限定的程序集名称才能工作)并摆脱Activator 调用(MemoryManager 是一个静态类)。此外,您需要添加正确的属性绑定标志(属性也是静态的)?
    • @Sergio0694 感谢您的更新 - 旧代码“出乎我的意料”,现在我将其更新为工作/测试示例。
    【解决方案2】:

    我认为您可以使用以前用于可移植类库的相同技巧 - Bait and Switch。它仍然是compatible with .NET Standard 2.0。这样您就可以为 UWP 创建一个特定的实现,否则就回退到标准实现。

    【讨论】:

    • 我不确定这是否是正确的方法,因为恕我直言,它违背了 .NET 标准库的全部要点,即定义与平台无关的代码而不是针对特定框架(我一直认为它类似于 POSIX 标准)。另外,为这个单一属性添加一个额外的 .dll 在这里似乎有点矫枉过正。
    • 我知道,但是对于特定于平台的功能,这仍然是您唯一的选择......在这种情况下,这看起来更干净。但是 try catch 方法更简单,虽然更脏......
    • 是的,我同意使用反射有点脏,但考虑到我在 lib 的其他地方使用它们,我现在可以接受这个解决方案。假设我希望未来的 UWP 更新将真正实现/支持更多的 .NET 标准 API,可能有一个通用 API 来检索当前使用的内存大小。我了解出于安全原因,Process 类已针对 UWP 应用程序锁定,但在这里我们只需要一种“只读”方式来检查内存使用情况,因此这似乎是合理的。
    • 是的,这很有意义,我实际上希望这能奏效,但它没有实现令人惊讶
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 2018-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多