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

| 我正尝试检测每次剪贴板数据更改。因此,我设置了一个计时器并使它连续检查
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();
}
运行时出现以下错误:   必须先将当前线程设置为单线程单元(STA)模式,然后才能进行OLE调用。 有人知道为什么吗?     
已邀请:
        它几乎是任何托管Windows GUI应用程序的线程模型。运行与UI线程接口的代码ergo的线程必须相同。如果您将启动路径的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线程)。为了在属于该特殊线程的对象上调用方法,您需要经过SynchronizationContext,我已将其作为App类的静态成员提供。 您可能还想考虑使用一个实际分派到主UI线程的计时器,那么您就不必再费心自己将其发布到SynchronizationContext了。     
        您的方法访问Clipboard类,这是一个OLE调用,需要调用方处于STA模式。这很可能是您的计时器出现问题,该计时器在其他线程上运行。这是一个链接,可以帮助您了解有关此的更多信息: http://social.msdn.microsoft.com/Forums/zh-CN/winforms/thread/2411f889-8e30-4a6d-9e28-8a46e66c0fdb/ 另外,这里是指向完整文章的链接,该文章介绍了如何通过利用Windows事件来监视剪贴板: http://www.radsoftware.com.au/articles/clipboardmonitor.aspx 我认为本文将为您提供一些有关如何更好地监视剪贴板的提示,从而可以避免此问题。虽然知道为什么会发生错误仍然很不错,但是有一种更好的方法可以完成此任务。     
        对此不完全确定,但是您是否尝试调用文本更改?我遇到了完全相同的错误(尽管在非常不同的情况下),并且调用一种更改控件属性的方法解决了它。 我创建了一个带有字符串参数的委托:
public delegate void TextBoxChangeDelegate(string text);
然后是将进行实际更改的方法:
void TextBoxChange(string text)
{
   MyTextBox.Text = text;
}
然后,我在线程进程中调用此方法(在您的情况下为timer事件):
public void ThreadService()
{
  while(Running)
  {
    Invoke(new TextBoxChangeDelegate(TextBoxChange), new object[] { \"New Value: \"+ strNewValue });
  }

}
这是在WinForms中。早在我第一次知道更改UI线程以外的线程上的控件属性会导致问题时,就回到了当初。很抱歉,如果这个距离与您尝试的距离还很近。     
        用计时器轮询剪贴板是非常不好的做法。剪贴板是共享资源,您将干扰其他正在监视剪贴板的应用(通过适当的剪贴板通知,即遵循规则)。而且您将与用户尝试执行的任何操作发生冲突。例如,当用户尝试将数据复制到剪贴板时,如果您已在轮询循环中将其打开以进行检查,则他会收到“无法打开剪贴板”错误或崩溃。请在MSDN中的剪贴板查看器上阅读:http://msdn.microsoft.com/zh-cn/library/ff468802(v=VS.85).aspx     
        这是因为您不能在线程委托中使用Windows控制,基本上计时器是一个线程,并且传递一个使用Windows控制的委托会导致问题。 检查这是否有帮助 http://social.msdn.microsoft.com/Forums/zh-CN/winforms/thread/2411f889-8e30-4a6d-9e28-8a46e66c0fdb/     

要回复问题请先登录注册