c# – 等待剪贴板文本更改(错误)

每次剪贴板数据发生变化时,我都会尝试检测.所以,我设置了一个计时器,让它不断检查Clipboard.GetText()的变化.

我正在使用以下代码:

public void WaitForNewClipboardData()
{
    //This is in WPF, Timer comes from System.Timers
    Timer timer = new Timer(100);
    timer.Elapsed += new ElapsedEventHandler(
        delegate(object a, ElapsedEventArgs b){
            if (Clipboard.GetText() != ClipBoardData)
            {
                SelectedText.Text = Clipboard.GetText();
                ClipBoardData = Clipboard.GetText();
                timer.Stop();
            }
        });
    timer.Start();
}

运行时出现以下错误:

Current thread must be set to singlethread apartment (STA) mode before OLE calls can be made.

有谁知道为什么?

解决方法:

它是基本上任何托管Windows GUI应用程序的线程模型.运行代码ergo与UI线程连接的线程必须是同一个.如果您将启动路径的SynchronizationContext维护在某个位置(您可以将其置于静态变量中),则可以向其发布消息.这些消息将最终在正确的线程上执行,您将不会收到此错误.

public partial class App : Application
{
    public static SynchronizationContext SynchronizationContext;

    protected override void OnStartup(StartupEventArgs e)
    {
        // This is my preferred way of accessing the correct SynchronizationContext in a WPF app
        SynchronizationContext = SynchronizationContext.Current;

        base.OnStartup(e);

        var mainWindow = MainWindow;

        var t = new Thread(() => {
            Thread.Sleep(3000);

            SynchronizationContext.Post(state => {
                mainWindow.Hide(); // this will not throw an exception
            }, null);

            mainWindow.Close(); // this will throw an exception
        });

        t.Start();
    }
}

所以,基本上,当你使用不同的线程(即定时器和不是什么)时,你需要记住原始的启动线程是特殊的(假设它是一个STA线程).为了在属于该特殊线程的对象上调用方法,您将通过我作为App类的静态成员提供的SynchronizationContext.

您可能还想考虑使用实际调度到主UI线程的计时器,然后您不必自己去发布到SynchronizationContext的麻烦.

上一篇:c# – 剪贴板监视器


下一篇:如何在C#中实现OLE服务器