如何使用任务使用Clipboard.GetText?

时间:2016-11-27 11:47:48

标签: c# multithreading task clipboard

我正在编写一个自动化旧软件的Windows表单应用程序。为了在该软件和我的应用程序之间传输信息,我使用剪贴板。单击旧软件上的按钮会将一些信息放入剪贴板。

要使用 Clipboard.GetText ,我应该从Windows窗体中调用它。但我并不想要UI线程上的所有内容。

当我在另一个任务中调用Clipboard.GetText时,我说它应该从STAThread调用Clipboard.GetText。

3 个答案:

答案 0 :(得分:4)

你将不得不改变你的期望。标准要求是只有UI线程与剪贴板交互。

从技术上讲,文档中提到的实际要求是只有single-threaded apartment (STA) threads才能访问剪贴板。因为大多数后台线程(如.NET中的ThreadPool类创建的线程)都是多线程单元(MTA)线程,所以它们无法访问剪贴板。你可以通过手动创建自己的STA线程并在其上运行消息泵来解决这个问题,但是使用UI线程要容易得多,这就是每个人所做的事情。

然而,尝试使用剪贴板在两个进程之间共享信息是一个糟糕的设计。剪贴板用于用户存储信息。你写入剪贴板的任何内容都会破坏用户存储的内容。如果您的应用程序执行此操作并覆盖我想要保留的内容,那么我将对您非常愤怒。

流程有更好的方式相互通信;搜索"进程间通信" (缩写为" IPC")用于各种想法。

答案 1 :(得分:2)

您的UI线程是STA。但这并不意味着您必须在UI线程中执行全部您的逻辑。您可以在后台执行除 UI行之外的所有行。通过将您的Clipboard.GetText调用回调到工作线程中的UI线程(假设您有Form或任何其他Control可用),可以在ctrl变量中进行操作):

//Do something
Func<string> getClipboardText = delegate() { return Clipboard.GetText(); };
string clipboardText = (string)ctrl.Invoke(getClipboardText);
//Do something else

答案 2 :(得分:1)

如果您不想同时使用Windows.Forms或Wpf剪贴板,则可以调用本机剪贴板api,如下所示:

How can I copy a string to clipboard within my console app WITHOUT adding a reference to System.Windows.Forms?

从剪贴板中获取字符串的示例

        OpenClipboard(IntPtr.Zero);

        var ptr = GetClipboardData(13);
        var s = Marshal.PtrToStringUni(ptr);
        Marshal.FreeHGlobal(ptr);
        CloseClipboard();

我用13作为剪贴板类型(CF_UNICODETEXT) 完整列表,你可以在这里看到: https://msdn.microsoft.com/de-de/library/windows/desktop/ff729168(v=vs.85).aspx