Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# CoWaitForMultipleHandles API不';不要表现得像文件所记载的那样_C#_.net_Windows_Winapi_Com - Fatal编程技术网

C# CoWaitForMultipleHandles API不';不要表现得像文件所记载的那样

C# CoWaitForMultipleHandles API不';不要表现得像文件所记载的那样,c#,.net,windows,winapi,com,C#,.net,Windows,Winapi,Com,这是由我看到的触发的。这本书可能太长了,所以请耐心听我说 显然,其行为与MSDN上的记录不符。 下面的代码(基于原始问题)是一个控制台应用程序,它使用测试Win32窗口启动STA线程,并尝试post和发送一些消息。它对CoWaitForMultipleHandles执行三种不同的测试,所有测试都不带COWAIT_WAITALL标志 测试#1旨在验证: COWAIT\u INPUTAVAILABLE如果设置,对CoWaitForMultipleHandles的调用将处理 如果队列存在输入,则返回S

这是由我看到的触发的。这本书可能太长了,所以请耐心听我说

显然,其行为与MSDN上的记录不符。

下面的代码(基于原始问题)是一个控制台应用程序,它使用测试Win32窗口启动STA线程,并尝试post和发送一些消息。它对
CoWaitForMultipleHandles
执行三种不同的测试,所有测试都不带
COWAIT_WAITALL
标志

测试#1旨在验证:

COWAIT\u INPUTAVAILABLE如果设置,对CoWaitForMultipleHandles的调用将处理 如果队列存在输入,则返回S_OK,即使输入已存在 已使用调用另一个函数看到(但未删除),例如 偷看消息

这种情况不会发生,
CoWaitForMultipleHandles
阻塞,并且在发出等待句柄信号之前不会返回。我确实假设任何挂起的消息都应该被视为输入(与
MsgWaitForMultipleObjectsEx
MWMO\u INPUTAVAILABLE
相同,它可以按预期工作)

测试#2旨在验证:

COWAIT_DISPATCH_WINDOW_消息启用窗口消息的发送 来自ASTA或STA中的CoWaitForMultipleHandles。ASTA中的默认值是no 窗口消息已调度,STA中的默认值仅为一小部分 已发送特殊情况的消息。该值在MTA和中没有意义 被忽略了

这也不行。当仅使用
COWAIT\u DISPATCH\u WINDOW\u MESSAGES
标志调用
CoWaitForMultipleHandles
时,它会立即返回错误
CO\u E\u NOT \u SUPPORTED
(0x80004021)。如果它是
COWAIT\u DISPATCH\u WINDOW\u MESSAGES | COWAIT\u DISPATCH\u CALLS
的组合,则调用会阻塞,但不会输出任何消息。

Test#3演示了使调用线程的Windows消息队列运行的唯一方法。它是
COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS | COWAIT_INPUTAVAILABLE
的组合虽然这显然是一种未记录的行为,但它确实会发送消息。

测试代码(准备运行的控制台应用程序):

使用系统;
使用System.Runtime.InteropServices;
使用系统线程;
使用System.Threading.Tasks;
名称空间控制台STAPP
{
静态类程序
{
//主要
静态void Main(字符串[]参数)
{
WriteLine(“启动STA线程…”);
RunStaThread();
Console.WriteLine(“\nSTA线程已完成”);
控制台。WriteLine(“按Enter键退出”);
Console.ReadLine();
}
//启动并运行STA线程
静态void RunStaThread()
{
变量线程=新线程(()=>
{
//创建一个简单的Win32窗口
IntPtr hwnd=CreateTestWindow();
//发布一些WM_测试消息
WriteLine(“发布一些WM_测试消息…”);
NativeMethods.PostMessage(hwnd,NativeMethods.WM_测试,新IntPtr(1),IntPtr.Zero);
NativeMethods.PostMessage(hwnd,NativeMethods.WM_测试,新IntPtr(2),IntPtr.Zero);
NativeMethods.PostMessage(hwnd,NativeMethods.WM_测试,新IntPtr(3),IntPtr.Zero);
//测试#1
Console.WriteLine(“\nTest#1.CoWaitForMultipleHandles,仅可输入COWAIT#U,按Enter键停止…”);
var task=ReadLineAsync();
uint指数;
var result=NativeMethods.CoWaitForMultipleHandles(
NativeMethods.COWAIT_可输入,
NativeMethods.INFINITE,
1,新[]{task.AsUnmanagedHandle()},
指数);
WriteLine(“结果:“+Result+”,队列中挂起的消息:”+(NativeMethods.GetQueueStatus(0x1FF)>>16!=0));
//测试#2
Console.WriteLine(\nTest#2.CoWaitForMultipleHandles与COWAIT(发送)窗口(发送)消息| COWAIT(发送)呼叫,按回车键停止));
task=ReadLineAsync();
结果=NativeMethods.CoWaitForMultipleHandles(
NativeMethods.COWAIT_调度_窗口_消息|
NativeMethods.COWAIT_调度_调用,
NativeMethods.INFINITE,
1,新[]{task.AsUnmanagedHandle()},
指数);
WriteLine(“结果:“+Result+”,队列中挂起的消息:”+(NativeMethods.GetQueueStatus(0x1FF)>>16!=0));
//测试#3
Console.WriteLine(\nTest#3.CoWaitForMultipleHandles,带有COWAIT_DISPATCH_WINDOW_消息| COWAIT_DISPATCH_CALLS | COWAIT_INPUTAVAILABLE,按Enter键停止…);
task=ReadLineAsync();
结果=NativeMethods.CoWaitForMultipleHandles(
NativeMethods.COWAIT_调度_窗口_消息|
NativeMethods.COWAIT_调度_调用|
NativeMethods.COWAIT_可输入,
NativeMethods.INFINITE,
1,新[]{task.AsUnmanagedHandle()},
指数);
WriteLine(“结果:“+Result+”,队列中挂起的消息:”+(NativeMethods.GetQueueStatus(0x1FF)>>16!=0));
});
SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
}
//
//助手
//
//创建一个窗口来处理消息
静态IntPtr CreateTestWindow()
{
//创建一个简单的Win32窗口
var hwndStatic=NativeMethods.CreateWindowEx(0,“Sta
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleTestApp
{
    static class Program
    {
        // Main 
        static void Main(string[] args)
        {
            Console.WriteLine("Starting an STA thread...");
            RunStaThread();

            Console.WriteLine("\nSTA thread finished.");
            Console.WriteLine("Press Enter to exit.");
            Console.ReadLine();
        }

        // start and run an STA thread
        static void RunStaThread()
        {
            var thread = new Thread(() =>
            {
                // create a simple Win32 window
                IntPtr hwnd = CreateTestWindow();

                // Post some WM_TEST messages
                Console.WriteLine("Post some WM_TEST messages...");
                NativeMethods.PostMessage(hwnd, NativeMethods.WM_TEST, new IntPtr(1), IntPtr.Zero);
                NativeMethods.PostMessage(hwnd, NativeMethods.WM_TEST, new IntPtr(2), IntPtr.Zero);
                NativeMethods.PostMessage(hwnd, NativeMethods.WM_TEST, new IntPtr(3), IntPtr.Zero);

                // Test #1
                Console.WriteLine("\nTest #1. CoWaitForMultipleHandles with COWAIT_INPUTAVAILABLE only, press Enter to stop...");
                var task = ReadLineAsync();

                uint index;
                var result = NativeMethods.CoWaitForMultipleHandles(
                    NativeMethods.COWAIT_INPUTAVAILABLE,
                    NativeMethods.INFINITE,
                    1, new[] { task.AsUnmanagedHandle() },
                    out index);
                Console.WriteLine("Result: " + result + ", pending messages in the queue: " + (NativeMethods.GetQueueStatus(0x1FF) >> 16 != 0));

                // Test #2
                Console.WriteLine("\nTest #2. CoWaitForMultipleHandles with COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS, press Enter to stop...");
                task = ReadLineAsync();

                result = NativeMethods.CoWaitForMultipleHandles(
                    NativeMethods.COWAIT_DISPATCH_WINDOW_MESSAGES | 
                        NativeMethods.COWAIT_DISPATCH_CALLS,
                    NativeMethods.INFINITE, 
                    1, new[] { task.AsUnmanagedHandle() },
                    out index);
                Console.WriteLine("Result: " + result + ", pending messages in the queue: " + (NativeMethods.GetQueueStatus(0x1FF) >> 16 != 0));

                // Test #3
                Console.WriteLine("\nTest #3. CoWaitForMultipleHandles with COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS | COWAIT_INPUTAVAILABLE, press Enter to stop...");
                task = ReadLineAsync();

                result = NativeMethods.CoWaitForMultipleHandles(
                    NativeMethods.COWAIT_DISPATCH_WINDOW_MESSAGES | 
                        NativeMethods.COWAIT_DISPATCH_CALLS | 
                        NativeMethods.COWAIT_INPUTAVAILABLE,
                    NativeMethods.INFINITE,
                    1, new[] { task.AsUnmanagedHandle() },
                    out index);
                Console.WriteLine("Result: " + result + ", pending messages in the queue: " + (NativeMethods.GetQueueStatus(0x1FF) >> 16 != 0));
            });

            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();

            thread.Join();
        }

        //
        // Helpers
        //

        // create a window to handle messages
        static IntPtr CreateTestWindow()
        {
            // Create a simple Win32 window 
            var hwndStatic = NativeMethods.CreateWindowEx(0, "Static", String.Empty, NativeMethods.WS_POPUP,
                0, 0, 0, 0, NativeMethods.HWND_MESSAGE, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

            // subclass it with a custom WndProc
            IntPtr prevWndProc = IntPtr.Zero;

            NativeMethods.WndProc newWndProc = (hwnd, msg, wParam, lParam) =>
            {
                if (msg == NativeMethods.WM_TEST)
                    Console.WriteLine("WM_TEST processed: " + wParam);
                return NativeMethods.CallWindowProc(prevWndProc, hwnd, msg, wParam, lParam);
            };

            prevWndProc = NativeMethods.SetWindowLong(hwndStatic, NativeMethods.GWL_WNDPROC,
                Marshal.GetFunctionPointerForDelegate(newWndProc));
            if (prevWndProc == IntPtr.Zero)
                throw new ApplicationException();

            return hwndStatic;
        }

        // call Console.ReadLine on a pool thread
        static Task<string> ReadLineAsync()
        {
            return Task.Run(() => Console.ReadLine());
        }

        // get Win32 waitable handle of Task object
        static IntPtr AsUnmanagedHandle(this Task task)
        {
            return ((IAsyncResult)task).AsyncWaitHandle.SafeWaitHandle.DangerousGetHandle();
        }
    }

    // Interop
    static class NativeMethods
    {
        [DllImport("user32")]
        public static extern IntPtr SetWindowLong(IntPtr hwnd, int nIndex, IntPtr dwNewLong);

        [DllImport("user32")]
        public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        public static extern IntPtr CreateWindowEx(
            uint dwExStyle, string lpClassName, string lpWindowName, uint dwStyle, 
            int x, int y, int nWidth, int nHeight, 
            IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);

        [DllImport("user32.dll")]
        public static extern bool PostMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        public static extern int MessageBox(IntPtr hwnd, string text, String caption, int options);

        [DllImport("ole32.dll", SetLastError = true)]
        public static extern uint CoWaitForMultipleHandles(uint dwFlags, uint dwTimeout,
           int cHandles, IntPtr[] pHandles, out uint lpdwindex);

        [DllImport("user32.dll")]
        public static extern uint GetQueueStatus(uint flags);

        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        public delegate IntPtr WndProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);

        public static IntPtr HWND_MESSAGE = new IntPtr(-3);

        public const int GWL_WNDPROC = -4;
        public const uint WS_POPUP = 0x80000000;

        public const uint WM_USER = 0x0400;
        public const uint WM_TEST = WM_USER + 1;

        public const uint COWAIT_WAITALL = 1;
        public const uint COWAIT_ALERTABLE = 2;
        public const uint COWAIT_INPUTAVAILABLE = 4;
        public const uint COWAIT_DISPATCH_CALLS = 8;
        public const uint COWAIT_DISPATCH_WINDOW_MESSAGES = 0x10;

        public const uint RPC_S_CALLPENDING = 0x80010115;

        public const uint WAIT_TIMEOUT = 0x00000102;
        public const uint WAIT_FAILED = 0xFFFFFFFF;
        public const uint WAIT_OBJECT_0 = 0;
        public const uint WAIT_ABANDONED_0 = 0x00000080;
        public const uint WAIT_IO_COMPLETION = 0x000000C0;

        public const uint INFINITE = 0xFFFFFFFF;
    }
}
Starting an STA thread... Post some WM_TEST messages... Test #1. CoWaitForMultipleHandles with COWAIT_INPUTAVAILABLE only, press Enter to stop... Result: 0, pending messages in the queue: True Test #2. CoWaitForMultipleHandles with COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS, press Enter to stop... Result: 0, pending messages in the queue: True Test #3. CoWaitForMultipleHandles with COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS | COWAIT_INPUTAVAILABLE, press Enter to stop... WM_TEST processed: 1 WM_TEST processed: 2 WM_TEST processed: 3 Result: 0, pending messages in the queue: False STA thread finished. Press Enter to exit.