为什么我的剪贴板侦听器被调用两次/应用程序打开两次?

我用C#写了一个简短的程序来监视剪贴板。 当某个string进入剪贴板时,程序必须用Process.Start打开(取决于string)。 一切工作正常,但有时应用程序正在打开两次。 我不知道为什么会这样。

namespace ClipboardMonitor { public class Form1 : System.Windows.Forms.Form { [DllImport("User32.dll")] protected static extern int SetClipboardViewer(int hWndNewViewer); [DllImport("User32.dll", CharSet=CharSet.Auto)] public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); [DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll")] static extern IntPtr GetConsoleWindow(); [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); const int SW_HIDE = 0; const int SW_SHOW = 5; [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetForegroundWindow(IntPtr hWnd); IntPtr nextClipboardViewer; private System.ComponentModel.Container components = null; public Form1() { InitializeComponent(); nextClipboardViewer = (IntPtr)SetClipboardViewer((int) this.Handle); var handle = GetConsoleWindow(); ShowWindow(handle, SW_HIDE); } protected override void Dispose( bool disposing ) { ChangeClipboardChain(this.Handle, nextClipboardViewer); if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } private void InitializeComponent() { this.WindowState = FormWindowState.Minimized; this.ShowInTaskbar = false; this.Name = "Form1"; } [STAThread] static void Main() { Application.Run(new Form1()); } protected override void WndProc(ref System.Windows.Forms.Message m) { const int WM_DRAWCLIPBOARD = 0x308; const int WM_CHANGECBCHAIN = 0x030D; switch(m.Msg) { case WM_DRAWCLIPBOARD: DisplayClipboardData(); SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; case WM_CHANGECBCHAIN: if (m.WParam == nextClipboardViewer) nextClipboardViewer = m.LParam; else SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; default: base.WndProc(ref m); break; } } void DisplayClipboardData() { Thread.Sleep(500); try { IDataObject iData = new DataObject(); iData = Clipboard.GetDataObject(); if (iData.GetDataPresent(DataFormats.Text)) { string path = iData.GetData(DataFormats.Text).ToString(); string[] words = path.Split('_'); if (words[0] == "startLO") { ProcessStartInfo info = new ProcessStartInfo(words[1]); Process p = Process.Start(info); } } else { // We doen niets. } } catch(Exception e) { MessageBox.Show(e.ToString()); } } } 

一种解释是,快速连续发生多个剪贴板事件。 这是相当普遍的。 你可以用一个“解决时间”延迟来防御这个问题。 即不是马上做出反应,而是设置一个计时器或者创建一个线程来“处理”一段时间。 随着更多的事件进入,请继续延期。 当解决时间最终到期时,定时器或线程被允许实际运行你的程序。