Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用剪贴板.GetText使用任务?_C#_Multithreading_Task_Clipboard - Fatal编程技术网

C# 如何使用剪贴板.GetText使用任务?

C# 如何使用剪贴板.GetText使用任务?,c#,multithreading,task,clipboard,C#,Multithreading,Task,Clipboard,我正在编写一个Windows窗体应用程序,它可以自动化一个旧软件。为了在该软件和我的应用程序之间传输信息,我使用剪贴板。单击旧软件上的按钮将一些信息放入剪贴板 对于使用剪贴板。GetText我应该从windows窗体调用它。但我不希望所有的东西都在UI线程上 在另一个任务中调用Clipboard.GetText时,我得到的提示是您应该从一个STAThread调用Clipboard.GetText。您必须改变您的期望。标准要求只有UI线程与剪贴板交互 从技术上讲,文档中提到的实际需求是,只有用户才

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

对于使用剪贴板。GetText我应该从windows窗体调用它。但我不希望所有的东西都在UI线程上


在另一个任务中调用Clipboard.GetText时,我得到的提示是您应该从一个STAThread调用Clipboard.GetText。

您必须改变您的期望。标准要求只有UI线程与剪贴板交互

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

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


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

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

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

        OpenClipboard(IntPtr.Zero);

        var ptr = GetClipboardData(13);
        var s = Marshal.PtrToStringUni(ptr);
        Marshal.FreeHGlobal(ptr);
        CloseClipboard();
我使用13作为剪贴板类型(CF_unicodext) 您可以在此处看到完整列表:
您的UI线程是STA。但这并不意味着您必须在UI线程中执行所有逻辑。您可以在后台执行除UI行以外的所有行。这可以通过整理
剪贴板来实现。GetText
从worker thrad回调UI线程(假设您有
表单
或任何其他可用的
控件
——在
ctrl
变量中):

//做点什么
Func getClipboardText=delegate(){返回剪贴板.GetText();};
string clipboardText=(string)ctrl.Invoke(getClipboardText);
//做点别的

请参见感谢您的回复。实际上,这不是一个客户的应用程序。有一个旧软件连接到主机并获取航班信息。这是终点站。我们编写了一个应用程序,并将其放在连接到大型机的旧软件旁边的服务器上。好吧,这很好,它解决了激烈的客户问题,但它并没有改变以下基本问题:(1)剪贴板不是设计用于多线程的,(2)与剪贴板相比,有一系列更好、更合适的跨进程通信机制。你完全正确,但我仅限于这样一个事实:我无法更改旧程序(这是一个封闭源代码,只有很少的技术文档)。这实际上并不能解决问题,它只是让你不被警告你在做蠢事。剪贴板使用COM协商数据格式,这就要求它只能与STA线程一起使用。P/调用本机API不会改变这一点。谢谢您的回答。你能帮我把GetClipboardData数据(一个句柄)转换成文本吗?@Mild请看更改后的答案。非常感谢。你忘了调用CloseClipboard。谢谢你的回复@Sefe。但就我而言,马克西姆的答案更适合我的问题。非常感谢你。
//Do something
Func<string> getClipboardText = delegate() { return Clipboard.GetText(); };
string clipboardText = (string)ctrl.Invoke(getClipboardText);
//Do something else