C# – System.Windows.Forms.Clipboard.GetDataObject()没有响应

有没有人知道为什么System.Windows.Forms.Clipboard.GetDataObject()在从主线程中调用System.Windows.Forms.Clipboard.Clear()之后从另一个线程调用它并且在主线程停止之前没有返回?

我写了一个示例程序来解释我的问题:

 public class ClipboardDemo { [STAThread] public static void Main(string[] args) { Thread.CurrentThread.Name = "MAIN_THREAD"; Thread clipboardViewerThread = new Thread(RunClipboardViewer); clipboardViewerThread.Name = "CLIPBOARD_VIEWER_THREAD"; clipboardViewerThread.SetApartmentState(ApartmentState.STA); Thread clipboardClearerThread = new Thread(RunClipboardClearer); clipboardClearerThread.Name = "CLIPBOARD_CLEARER_THREAD"; clipboardClearerThread.SetApartmentState(ApartmentState.STA); Console.WriteLine("Starting " + clipboardViewerThread.Name + ", expecting initial WM_DRAWCLIPBOARD message..."); clipboardViewerThread.Start(); Thread.Sleep(1000); Console.WriteLine("Clearing clipboard from " + clipboardClearerThread.Name + ", expecting WM_DRAWCLIPBOARD message..."); clipboardClearerThread.Start(); clipboardClearerThread.Join(); Console.WriteLine("Clearing clipboard from " + Thread.CurrentThread.Name + ", expecting WM_DRAWCLIPBOARD message..."); Clipboard.Clear(); Thread.Sleep(1000); Application.Exit(); Console.WriteLine("\t" + Thread.CurrentThread.Name + " stopped!"); } private static void RunClipboardViewer() { ClipboardViewer viewer = new ClipboardViewer(); viewer.ViewClipboard(); viewer.Dispose(); } private static void RunClipboardClearer() { Clipboard.Clear(); } } internal class ClipboardViewer : NativeWindow, IDisposable { private const int WM_CREATE = 0x0001; private const int WM_DRAWCLIPBOARD = 0x0308; private const int WM_CHANGECBCHAIN = 0x030D; private IntPtr nextViewer; public void ViewClipboard() { base.CreateHandle(new CreateParams()); Application.Run(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected override void WndProc(ref Message m) { base.WndProc(ref m); switch (m.Msg) { case WM_CREATE: nextViewer = User32Interop.SetClipboardViewer(base.Handle); break; case WM_DRAWCLIPBOARD: if (nextViewer != IntPtr.Zero) { User32Interop.SendMessage(nextViewer, WM_DRAWCLIPBOARD, m.WParam, m.LParam); } Console.WriteLine("\tClipboard changed in " + Thread.CurrentThread.Name + ". Trying to receive data object..."); Clipboard.GetDataObject(); Console.WriteLine("\tData object received!"); break; case WM_CHANGECBCHAIN: if (m.WParam == nextViewer) { nextViewer = m.LParam; } else if (nextViewer != IntPtr.Zero) { User32Interop.SendMessage(nextViewer, WM_CHANGECBCHAIN, m.WParam, m.LParam); } break; } } private void Dispose(bool disposing) { if (disposing) { User32Interop.ChangeClipboardChain(base.Handle, nextViewer); } base.DestroyHandle(); } ~ClipboardViewer() { Dispose(false); } } internal static class User32Interop { [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); } 

格式化的输出是:

 Starting CLIPBOARD_VIEWER_THREAD, expecting initial WM_DRAWCLIPBOARD message... Clipboard changed in CLIPBOARD_VIEWER_THREAD. Trying to receive data object... Data object received! Clearing clipboard from CLIPBOARD_CLEARER_THREAD, expecting WM_DRAWCLIPBOARD message... Clipboard changed in CLIPBOARD_VIEWER_THREAD. Trying to receive data object... Data object received! Clearing clipboard from MAIN_THREAD, expecting WM_DRAWCLIPBOARD message... Clipboard changed in CLIPBOARD_VIEWER_THREAD. Trying to receive data object... MAIN_THREAD stopped! Data object received! 

正如您在最后三行中看到的那样, System.Windows.Forms.Clipboard.GetDataObject()在主线程停止时返回,但不是更早。 有人知道这个问题的解决方案吗?

提前致谢!

您正在做正确的事情,为工作线程选择STA并让它们进行消息循环。 除了一个:你的主线程。 它只是偶然泵送。 Thread.Join()调用使CLR泵。 但Thread.Sleep()不会泵。 您可以随意替换它并修复您的问题:

  var dummy = new AutoResetEvent(false); dummy.WaitOne(1000); 

但这是一个黑客。 我意识到这只是一个测试应用程序,想想你的真实会是什么样子。