WMI 事件观察器性能问题

WMI Event Watcher Performance Problems

我编写了一些在大多数机器上运行良好的 WMI 代码。但是在某些机器上(几乎所有基于 SSD 的 mac),此代码会导致巨大的性能问题。它会导致 WMIPrvSe 进程不断命中 I/O 其他。如果您 运行 另一个应用程序进行相同的观看,那么它会变慢到爬行到软件变得无法使用的程度。

            System.Management.WqlEventQuery     queryIn;
            System.Management.WqlEventQuery     queryOut;
            System.Management.ManagementScope   scope   = new System.Management.ManagementScope( "root\CIMV2" );
            scope.Options.EnablePrivileges      = true;

            try
            {
                queryIn = new System.Management.WqlEventQuery();
                queryIn.EventClassName          = "__InstanceCreationEvent";
                queryIn.WithinInterval          = new TimeSpan( 0, 0, 1 );
                //queryIn.GroupWithinInterval       = new TimeSpan( 0, 0, 0 );
                queryIn.Condition               = @"TargetInstance ISA 'Win32_DiskDrive' AND TargetInstance.InterfaceType = 'USB'";
                mUSBWatcherIn = new System.Management.ManagementEventWatcher( scope, queryIn );

                //adds event handler that’s is fired when the insertion event occurs
                mUSBWatcherIn.EventArrived += new System.Management.EventArrivedEventHandler( USBInserted );

                queryOut = new System.Management.WqlEventQuery();
                queryOut.EventClassName         = "__InstanceDeletionEvent";
                queryOut.WithinInterval         = new TimeSpan( 0, 0, 1 );
                //queryOut.GroupWithinInterval  = new TimeSpan( 0, 0, 0 );
                queryOut.Condition              = @"TargetInstance ISA 'Win32_DiskDrive' AND TargetInstance.InterfaceType = 'USB'";
                mUSBWatcherOut = new System.Management.ManagementEventWatcher( scope, queryOut );

                //adds event handler that’s is fired when the insertion event occurs
                mUSBWatcherOut.EventArrived += new System.Management.EventArrivedEventHandler( USBRemoved );

                mUSBWatcherIn.Start();//run the watcher
                mUSBWatcherOut.Start();
            }
            catch (Exception e)
            {
                System.Windows.Forms.MessageBox.Show( e.Message );
                StopUSBWatcher();
            }

有人知道这里会发生什么吗?如果我删除这段代码,那么它就可以完美运行。在其他机器上,它工作得很好。这很奇怪。非常感谢任何想法!

所以我还没有找出导致问题的原因,但我现在已经使用 WM_DEVICECHANGE.

实现了相同的功能

这是我的互操作设置:

    [System.Runtime.InteropServices.DllImport( "user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall )]
    private static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags);

    [System.Runtime.InteropServices.DllImport( "user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall )] 
    private static extern bool UnregisterDeviceNotification(IntPtr handle);

    [System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
    static extern IntPtr GetWindowLongPtr( IntPtr hWnd, int nIndex );

    [System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
    static extern int GetWindowLong( IntPtr hWnd, int nIndex );

    [System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
    static extern IntPtr SetWindowLongPtr( IntPtr hWnd, int nIndex, IntPtr newLong );

    [System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
    static extern int SetWindowLong( IntPtr hWnd, int nIndex, int newLong );


    delegate IntPtr WndProcDelegate( IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam );

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    static extern IntPtr CallWindowProc( IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam );

    public const    int             GWLP_WNDPROC    = -4;

    [System.Runtime.InteropServices.StructLayout( System.Runtime.InteropServices.LayoutKind.Sequential )]
    private struct DevBroadcastDeviceinterface
    {
        internal int Size;
        internal int DeviceType;
        internal int Reserved;
        internal Guid ClassGuid;
        internal short Name;
    }

    const int DBT_DEVTYPVOLUME = 0x00000002;  
    const int DBT_DEVTYPDEVICEINTERFACE = 5;

    static readonly Guid GuidDevinterfaceUSBDevice = new Guid( "A5DCBF10-6530-11D2-901F-00C04FB951ED" );

而实际的设置代码如下:

        DevBroadcastDeviceinterface dbi = new DevBroadcastDeviceinterface
           {
               DeviceType = DBT_DEVTYPDEVICEINTERFACE,//DBT_DEVTYPVOLUME,
               Reserved = 0,
               ClassGuid = GuidDevinterfaceUSBDevice,
               Name = 0
           };

        dbi.Size = System.Runtime.InteropServices.Marshal.SizeOf( dbi );
        IntPtr buffer = System.Runtime.InteropServices.Marshal.AllocHGlobal( dbi.Size );
        System.Runtime.InteropServices.Marshal.StructureToPtr( dbi, buffer, true );

        IntPtr i = RegisterDeviceNotification( Handle, buffer, 0 );

        System.Runtime.InteropServices.Marshal.FreeHGlobal( buffer );

        if ( IntPtr.Size == 4 )
        {
            oldWndProc  = new IntPtr( SetWindowLong( Handle, GWLP_WNDPROC, System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( newWndProc ).ToInt32() ) );
        }
        else
        { 
            oldWndProc  = SetWindowLongPtr( Handle, GWLP_WNDPROC, System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( newWndProc ) );
        }