【问题标题】:How to use Clipboard.GetText using a Task?如何使用任务使用 Clipboard.GetText?
【发布时间】:2016-11-27 11:47:48
【问题描述】:

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

对于使用 Clipboard.GetText 我应该从 Windows 窗体中调用它。但我不希望 UI 线程上的所有内容。

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

【问题讨论】:

标签: c# multithreading task clipboard


【解决方案1】:

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

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

但是,尝试使用剪贴板在两个进程之间共享信息是一个糟糕的设计。剪贴板旨在供 用户 存储信息。您写入剪贴板的任何内容都会破坏用户存储在那里的任何内容。如果你的应用程序这样做,并覆盖了我想保留的东西,我会非常生你的气。

进程之间有更好的通信方式;搜索“进程间通信”(缩写为“IPC”)以获得各种想法。

【讨论】:

  • 感谢您的回复。实际上,它不是针对客户的应用程序。有一个旧软件可以连接到大型机并获取航班信息。这是一个终端。我们编写一个应用程序并将其放在连接到大型机的旧软件旁边的服务器上。
  • 嗯,这很好,它解决了客户的愤怒问题,但它并没有改变以下基本问题:(1) 剪贴板不是为多线程使用而设计的,(2)是一系列比剪贴板更好、更合适的跨进程通信机制。
  • 你说得完全正确,但我仅限于我无法更改旧程序(这是一个只有很少技术文档的封闭源代码。)
【解决方案2】:

您的 UI 线程是一个 STA。但这并不意味着您必须在 UI 线程中执行所有您的逻辑。您可以在后台执行除了 UI 行之外的所有行。这可以通过将您的 Clipboard.GetText 从您的工作线程调用回 UI 线程来实现(假设您有一个 Form 或任何其他 Controlavailable - 在 ctrlvariable 中):

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

【讨论】:

  • 感谢您的回复@Sefe。但就我而言,Maksim answer 更适合我的问题。非常感谢。
【解决方案3】:

如果您不想使用 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

【讨论】:

  • 这实际上并不能解决问题,它只是让您不会收到警告说您正在尝试做一些愚蠢的事情。剪贴板使用 COM 来协商数据格式,这就是要求它只能与 STA 线程一起使用的要求。 P/调用本机 API 不会改变这一点。
  • 感谢您的回答。请您帮我将 GetClipboardData 数据(它是一个句柄)转换为一个对象到一个文本?
  • @Milad 看到改变的答案。
  • 非常感谢。
  • 您忘记调用 CloseClipboard。
猜你喜欢
  • 2011-02-10
  • 2016-03-17
  • 1970-01-01
  • 2017-11-02
  • 1970-01-01
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
相关资源
最近更新 更多