CoWaitForMultipleHandles API的行为不像logging

CoWaitForMultipleHandles API的行为不像logging,第1张

概述CoWaitForMultipleHandles API的行为不像logging

这是我看到的另一个问题引发的。 阅读可能太长,请耐心等待。

显然, CoWaitForMultipleHandles行为不像MSDN上logging的那样。

下面的代码(基于原始问题)是一个控制台应用程序,它启动一个testingWin32窗口的STA线程,并尝试发布和泵送一些消息。 它在CoWaitForMultipleHandles上做了三个不同的testing,都没有 COWAIT_WAITALL标志。

testing#1旨在valIDation这一点 :

Visual Studio ClickOnce部署是否自动包含必要的.NET框架?

在C#.NET中使用 *** 作系统的文件types图像

进程树

如何设置箱子风扇速度

从C#中正在增长的文件中读取?

[b]COWAIT_inputAVAILABLE如果已设置,则即使input已经被查看(但未被删除),但对CoWaitForMultipleHandles的调用将返回S_OK,如果队列中存在input,则会调用另一个函数(例如PeekMessage)。这不会发生, CoWaitForMultipleHandles阻塞,并不会返回,直到等待手柄信号。 我假设任何挂起的消息应该被视为input (与MWMO_inputAVAILABLE的MsgWaitForMultipleObjectsEx相同,预计工作)。testing#2旨在valIDation这一点 :COWAIT_disPATCH_WINDOW_MESSAGES允许从ASTA或STA中的CoWaitForMultipleHandles分派窗口消息。 在ASTA中默认是没有窗口消息派发,STA中的默认只是一小组调度的特殊的消息。 该值在MTA中没有意义,并被忽略。这也不pipe用。 当CoWaitForMultipleHandles调用COWAIT_disPATCH_WINDOW_MESSAGES时,会立即返回错误CO_E_NOT_SUPPORTED (0x80004021)。 如果是COWAIT_disPATCH_WINDOW_MESSAGES | COWAIT_disPATCH_CALLS的组合 COWAIT_disPATCH_WINDOW_MESSAGES | COWAIT_disPATCH_CALLS ,呼叫块但不会泵送任何消息。testing#3演示了我可以使CoWaitForMultipleHandles泵送调用线程的windows消息队列的唯一方法。 这是COWAIT_disPATCH_WINDOW_MESSAGES | COWAIT_disPATCH_CALLS | COWAIT_inputAVAILABLE的组合 COWAIT_disPATCH_WINDOW_MESSAGES | COWAIT_disPATCH_CALLS | COWAIT_inputAVAILABLE COWAIT_disPATCH_WINDOW_MESSAGES | COWAIT_disPATCH_CALLS | COWAIT_inputAVAILABLE 。 这确实泵和发送消息,虽然显然这是一个无证的行为。testing代码 (一个准备运行的控制台应用程序):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,new IntPtr(2),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,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,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,NativeMethods.HWND_MESSAGE,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,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,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,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; } }输出:启动STA线程...发布一些WM_TEST消息...testing#1。[/b] CoWaitForMultipleHandles只有COWAIT_inputAVAILABLE,按Enter停止...结果:0,等待队列中的消息:Truetesting#2。 CoWaitForMultipleHandles与COWAIT_disPATCH_WINDOW_MESSAGES | COWAIT_disPATCH_CALLS,按Enter停止...结果:0,等待队列中的消息:Truetesting#3 CoWaitForMultipleHandles与COWAIT_disPATCH_WINDOW_MESSAGES | COWAIT_disPATCH_CALLS | COWAIT_inputAVAILABLE,按Enter停止...WM_TEST处理:1WM_TEST处理:2WM_TEST处理:3结果:0,等待队列中的消息:FalseSTA线程完成。按Enter键退出。所有的testing都是在windows 8.1 Pro 64bit + NET v4.5.1下完成的。我误读了文档还是错过了其他的东西?我应该报告这是一个错误(至less,在文档中的错误)?应该避免使用CoWaitForMultipleHandles并用基于MsgWaitForMultipleObjectsEx (其行为符合文档)的解决schemereplace?[更新]在windows 7下, COWAIT_disPATCH_WINDOW_MESSAGES和COWAIT_disPATCH_CALLS被支持, CoWaitForMultipleHandles失败, E_INVALIDARG (0x80070057)。 当用零作为标志进行调用时,它不会被泵送。我可以使用C#/ .NET以编程方式禁用窗口自动播放function吗?在正在运行的程序中堆栈跟踪(在windows中等同于pstack)windows 10虚拟机上的Visual Studio – 性能较差测量下载速度我们可以在我们的安装包中捆绑mono吗?CoWaitForMultipleHandles用于处理CoWaitForMultipleHandles中的COM窗口消息(例如,跨公寓编组)和其他一些(不要问我是哪个),或者简单地在MTA中阻塞。 在这篇博文中,克里斯·布鲁姆(Chris Brumme)的“托管阻塞”(Managed blocking)指出, CWFMH处理“恰到好处”的窗口消息。 但是,由于它会在队列中留下任何非COM发布的窗口消息,所以队列可能仍会填满,而不会使用COM窗口消息。根据这份文件,“将windows 8 Consumer PrevIEw应用程序迁移到windows 8 Release PrevIEw” ,它说:windows Store应用程序不再支持CoWaitForMultipleHandles函数。 另外,以下CoWait_Flags已被删除:COWAIT_disPATCH_CALLSCOWAIT_disPATCH_WINDOW_MESSAGES如果你真的想处理所有的消息,你应该在带有GetMessage的消息循环中使用MsgWaitForMultipleObjectsEx ,或者在PM_REMOVE使用PeekMessage 。 这样做意味着潜在的狂潮狂潮。 您仍然不能控制从堆栈中的其他组件进一步调用STA。 也就是说,一个模式对话框(例如,公开对话框)可能会在简单的旧窗口消息循环中抽取每个消息,但是一些框架可能会调用CoWaitForMultipleHandles 。底线是,如果您正在进行密集的处理或阻塞 *** 作,则将其委派给另一个线程(可能使用队列),并且如果需要,在 *** 作完成后告诉调用UI线程更新。这与例如冗长的UI调用(如olE嵌入或模式对话框)不同,其中通常沿着堆栈有一个窗口消息循环。 或者从冗长而可碎的/可恢复的 *** 作(例如一个状态机),在那里你可以通过稍微处理消息来进行协作,或者使用等待函数,当有消息时返回,所以你可以在再次等待之前处理它们。小心,这只适用于一个手柄; 对于多个句柄(例如互斥体),您可能希望全部或全部为零,而下一个最佳方法是一个活动循环,对WaitForMultipleObjects进行超时调用,然后使用带有PM_REMOVE窗口消息循环的PeekMessage进行PM_REMOVE 。 这是一个边界线的情况,对于用户关注的中心UI应用程序来说是可以接受的(例如,这是他们的主要工作),但是如果这样的代码可以在无人值守和按需的情况下运行,这是不可接受的。 除非您确定需要在STA或UI线程中发生,否则我的建议是不要这样做。最后,您可能应该在Microsoft Connect上打开一个错误,至少要更新文档。 或者实际上使其工作“预期”。 总结

以上是内存溢出为你收集整理的CoWaitForMultipleHandles API的行为不像logging全部内容,希望文章能够帮你解决CoWaitForMultipleHandles API的行为不像logging所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1273095.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存