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

问题描述 投票:0回答:3

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

对于使用 Clipboard.GetText 我应该从 Windows 窗体中调用它。但我不希望一切都在 UI 线程上。

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

c# multithreading task clipboard
3个回答
5
投票

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

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

然而,一开始尝试使用剪贴板在两个进程之间共享信息是一个糟糕的设计。剪贴板供“用户”存储信息。您写入剪贴板的任何内容都会破坏用户存储在那里的任何内容。如果你的应用程序这样做,并覆盖了我想保留的东西,我会对你非常愤怒。 进程之间有更好的通信方式;搜索“进程间通信”(缩写为“IPC”)以获取各种想法。


3
投票
Clipboard.GetText

回调从工作线程编组回 UI 线程来实现(假设您有 Form 或任何其他可用的 Control - 在

ctrl
变量中):

//Do something Func<string> getClipboardText = delegate() { return Clipboard.GetText(); }; string clipboardText = (string)ctrl.Invoke(getClipboardText); //Do something else
    
如果您不想使用 Windows.Forms 或 Wpf 剪贴板,您可以调用原生剪贴板 api,如下所示:

如何在控制台应用程序中将字符串复制到剪贴板而不添加对 System.Windows.Forms 的引用?

1
投票

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

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


// Init the Output Variable: string Output = string.Empty; // Run inside a Task: await Task.Run(() => { Thread thread = new Thread(() => { Output = Clipboard.GetText(TextDataFormat.Text); }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); });

© www.soinside.com 2019 - 2024. All rights reserved.