简体   繁体   English

使用剪贴板的C#多线程应用程序

[英]C# Multithread application using Clipboard

I'm workin on a multi-thread application and I face the issue of having to use the clipboard (I'm working with the Qlikview API - and I need to copy tables into excel) and the problem is that I think what will happen is something like this: On thread#1 I open the QW document and copy the table, and before I get to paste it in the excel sheet, thread#2 comes along and uses the clipboard to copy table from its document. 我正在研究一个多线程应用程序,我遇到了必须使用剪贴板的问题(我正在使用Qlikview API - 我需要将表复制到excel中)问题是我认为会发生什么是这样的:在线程#1上打开QW文档并复制表,在我将它粘贴到excel表之前,线程#2出现并使用剪贴板从其文档中复制表。 I'm curious whether it is even possible to use the clipboard from a multithreading application? 我很好奇是否可以使用多线程应用程序中的剪贴板? I've read all sorts of things about using the clipboard and the only clear thing that I understood about it is that the method must be STA (?). 我已经阅读了有关使用剪贴板的各种各样的事情,我理解的唯一明确的事情是该方法必须是STA(?)。 So I'm kind of confused right now. 所以我现在很困惑。 Thank you 谢谢

Since the clipboard is a shared resource, you need to be very careful. 由于剪贴板是共享资源,因此您需要非常小心。 It is indeed very likely that the operation in thread1 will be preempted by thread2. 确实很可能thread1中的操作将被thread2抢占。 You should be able to use critical sections to get around that, but... you need to consider that other applications on the system are also involved, in ways that are hard to predict. 您应该能够使用关键部分来解决这个问题,但是......您需要考虑系统上的其他应用程序也会以难以预测的方式参与其中。 Other clipboard listeners will be doing their thing, possibly pasting the data into themselves, or opening the clipboard to "peek" at the contents. 其他剪贴板监听器将做他们的事情,可能将数据粘贴到自己,或打开剪贴板“窥视”内容。 This will foil your attempts to quickly copy/paste data, as you will probably need to wait 1000ms or so, after copying, before you can reliably paste it. 这将阻止您快速复制/粘贴数据的尝试,因为您可能需要等待1000毫秒左右,在复制之后,才能可靠地粘贴它。 You need to consider what's going to happen if the user has a clipboard extender running (you will be filling it up with your crap). 你需要考虑如果用户有一个剪贴板扩展器运行会发生什么(你会用你的垃圾填满)。 How about remote desktop? 远程桌面怎么样? You will have to wait for the clipboard sync across the network, which in some cases, means that you could have yet another set of clipboard monitoring applications eager to examine your clipboard data, before you get a chance to paste it. 您将不得不等待网络上的剪贴板同步,这在某些情况下意味着您可能还有另一组剪贴板监视应用程序,希望在您有机会粘贴它之前检查剪贴板数据。

Then consider the fact that the clipboard is intended for the user's convenience, not as a crutch for the programmer. 然后考虑这样一个事实,即剪贴板是为了方便用户而不是程序员的拐杖。

If you continue along this path, you are surely doomed. 如果你继续沿着这条道路前进,你肯定会注定失败。 It's a bad idea, and impossible to implement without causing collateral damage. 这是一个坏主意,在不造成附带损害的情况下无法实施。 You should re-think your design. 你应该重新考虑你的设计。 And no, I do not have any better ideas. 不,我没有更好的想法。

Well, with multithreading, you can lock parts of the code that only one thread can run simultaneously. 好吧,使用多线程,您可以锁定只有一个线程可以同时运行的代码部分。 This is generally done to get a lock on resources that cannot be accessed simultaneously (like your clipboard example). 这通常是为了锁定无法同时访问的资源(如剪贴板示例)。

You define the following (in this example private , so it would be in the class where you want to put your lock): 您定义以下内容(在此示例中为private ,因此它将位于您要放置锁的类中):

private readonly System.Object MyLock = new System.Object();

And then use 然后使用

lock (MyLock)
{
    // Locked Code
}

Now, no more than one thread can run the code inside the lock. 现在,只有一个线程可以运行锁内的代码。

Note: in your case, this might still give problems if other applications/users start using the clipboard. 注意:在您的情况下,如果其他应用程序/用户开始使用剪贴板,这可能仍会出现问题。 If possible, you might want to consider using something different than the clipboard. 如果可能,您可能需要考虑使用与剪贴板不同的内容。

MSDN Thread Synchronization MSDN线程同步

I had been facing the same issue some days ago when working on an specific automation. 几天前我在处理特定的自动化时遇到了同样的问题。 I was able to overcome this by blocking the processes while using the ClipBoard object, thus if the first thread needs to use the ClipBoard the others will need to wait for the process to finish. 我能够通过在使用ClipBoard对象时阻止进程来克服这个问题,因此如果第一个线程需要使用ClipBoard,则其他线程需要等待进程完成。 This way we can guarantee that we won't get wrong behavior during the paste of data in somewhere, since there will be no conflict on this resource. 通过这种方式,我们可以保证在某些地方粘贴数据时不会出现错误行为,因为此资源不会发生冲突。

So, my approach was to create a control variable in the environment ( Environment.SetEnvironmentVariable ) named "CLIPBOARD_INUSE" and set it to true when an specific thread needs to perform ClipBoard methods. 因此,我的方法是在环境( Environment.SetEnvironmentVariable )中创建一个名为“CLIPBOARD_INUSE”的控制变量,并在特定线程需要执行ClipBoard方法时将其设置为true In the other threads, an while loop checks whether the variable "CLIPBOARD_INUSE" is false (resource is available) (make use of Thread.Sleep() before checking again). 在其他线程中,while循环检查变量“CLIPBOARD_INUSE”是否为false(资源可用)(在再次检查之前使用Thread.Sleep() )。 When the first thread finishes using the ClipBoard it's time to release the resource by setting the control variable we created back to false , so the next thread needing the ClipBoard can use it. 当第一个线程使用ClipBoard完成时,是时候通过将我们创建的控制变量设置为false来释放资源,因此需要ClipBoard的下一个线程可以使用它。

Hope you find this solution helpful as I did. 希望您能像我一样找到这个解决方案。

Regards, 问候,

Bruno Costa. 布鲁诺科斯塔。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM