How to set MinWorkingSet and MaxWorkingSet in a 64-bit .NET process?

前端 未结 2 1577
南旧
南旧 2021-01-13 07:48

How do I set MinWorkingSet and MaxWorking set for a 64-bit .NET process?

p.s. I can set the MinWorkingSet and MaxWorking set for a 32-bit process, as follows:

<
2条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-13 08:19

    All you have to do is change your declaration like so:

    [DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", 
        SetLastError = true, CallingConvention = CallingConvention.StdCall)]
    internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess, 
        long dwMinimumWorkingSetSize, long dwMaximumWorkingSetSize);
    

    The reason is because of the definition of the SetProcessWorkingSetSize function:

    BOOL WINAPI SetProcessWorkingSetSize(
      _In_  HANDLE hProcess,
      _In_  SIZE_T dwMinimumWorkingSetSize,
      _In_  SIZE_T dwMaximumWorkingSetSize
    );
    

    Note that it doesn't use a DWORD (as 32-bit integer) but a SIZE_T, which is defined as:

    The maximum number of bytes to which a pointer can point. Use for a count that must span the full range of a pointer. This type is declared in BaseTsd.h as follows:

    typedef ULONG_PTR SIZE_T;
    

    This means that it's a 64-bit value, hence the ability to change to a long and have the function work on 64-bit systems. Also, from the section of MSDN titled "Common Visual C++ 64-bit Migration Issues":

    size_t, time_t, and ptrdiff_t are 64-bit values on 64-bit Windows operating systems.

    However, this presents a bit of a dilemma, in that you don't want to have to compile platform-specific assemblies (that would be a PITA). You can get around this by taking advantage of the EntryPoint field on the DllImportAttribute class (which you're already doing) to have two method declarations:

    [DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", 
        SetLastError = true, CallingConvention = CallingConvention.StdCall)]
    internal static extern bool SetProcessWorkingSetSize32(IntPtr pProcess, 
        int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
    
    [DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", 
        SetLastError = true, CallingConvention = CallingConvention.StdCall)]
    internal static extern bool SetProcessWorkingSetSize64(IntPtr pProcess, 
        long dwMinimumWorkingSetSize, long dwMaximumWorkingSetSize);
    

    Now you have two separate signatures. However, knowing which signature to call is still an issue. You don't want to place conditional checks everywhere. To that end, I'd recommend creating a method that performs the check for you and call that.

    You'll want to use the Is64BitProcess property on the Environment class to make this determination. Don't use the Is64BitOperatingSystem property. You want the former because 32-bit processes can be run on 64-bit operating systems, and you want to make sure that your code is resilient to that; just checking to see if the operating system is 64 bit doesn't give you the entire picture.

提交回复
热议问题