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

3
我正在开发一个多线程应用程序,并且我面临着使用剪贴板的问题(我正在使用 Qlikview API - 我需要将表格复制到 Excel 中),问题是我认为会出现这样的情况:在线程#1中,我打开 QW 文档并复制表格,在将其粘贴到 Excel 工作表之前,线程#2来了并使用剪贴板从其文档中复制表格。我想知道是否可以从多线程应用程序中使用剪贴板?我已经阅读了关于如何使用剪贴板的各种文献,唯一我明白的清楚的是该方法必须是STA(?)。所以我现在有点困惑。谢谢

你尝试过了吗?你遇到了错误吗?请发布一些代码。 - BRAHIM Kamel
如果可能的话,我会避免以这种方式使用剪贴板。难道没有办法使用 Qlikview API 在不使用剪贴板的情况下获取数据吗?如果可以,您绝对可以使用 Excel 自动化互操作性将数据直接插入工作表,而无需使用剪贴板。 - Baldrick
我受限于API提供的导出功能。目前,我将所有表格导出为XML文件,然后计划将它们反序列化为数据表..然后使用openXML创建Excel。这似乎是一个相当紧密的计划,直到我意识到使用这种方法不仅会丢失格式,而且对于具有行跨度和列跨度的复杂表格,我似乎会丢失重要的行和列 - 在导出后,qlikview并没有提供准确的XML。它也可以导出到Excel,但没有模板化可能性,并且无法在同一Excel文件中导出多个表格。 - Vlad
3个回答

3

使用多线程技术,您可以锁定只有一个线程可以同时运行的代码部分。通常这样做是为了在无法同时访问资源的情况下获取锁定(例如剪贴板示例)。

您可以定义以下内容(在此示例中为private,因此应该放在要放置锁定的类中):

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

然后使用

lock (MyLock)
{
    // Locked Code
}

现在,只有一个线程可以在锁内运行代码。

注意:在您的情况下,如果其他应用程序/用户开始使用剪贴板,这可能仍会导致问题。如果可能的话,您可能需要考虑使用不同于剪贴板的东西。

MSDN 线程同步


3
由于剪贴板是一种共享资源,你需要非常小心。很可能线程1中的操作会被线程2抢占。你应该能够使用关键部分来解决这个问题,但是......你需要考虑到系统上的其他应用程序也在以难以预测的方式参与其中。其他剪贴板监听器将执行它们的操作,可能将数据粘贴到自己的应用程序中,或者打开剪贴板来“窥视”内容。这将破坏你快速复制/粘贴数据的尝试,因为你可能需要等待1000毫秒左右,在复制后才能可靠地粘贴它。
你需要考虑如果用户运行了剪贴板扩展程序会发生什么情况(你将填充它们的垃圾)。远程桌面怎么办?你将不得不等待剪贴板在网络上同步,而在某些情况下,这意味着你可能还有另一组剪贴板监视应用程序渴望检查你的剪贴板数据,然后再粘贴它。
考虑到剪贴板旨在方便用户使用,而不是作为程序员的支撑,如果你继续沿着这条路走,你肯定注定要失败的。这是一个坏主意,不可能在不造成附带损害的情况下实现。你应该重新思考你的设计。不过,我没有更好的想法。

1
谢谢你,克里斯。你指出了一些非常好的观点。不,我还没开始做这个,因为我想这可能是不可能的——即使我没有意识到所有的影响。祝你有美好的一天! - Vlad

0
我几天前在处理一个特定的自动化时遇到了同样的问题。我通过使用 ClipBoard 对象阻止进程来克服这个问题,因此如果第一个线程需要使用 ClipBoard,则其他线程将需要等待该进程完成。这样我们就可以保证在某个地方粘贴数据时不会出现错误行为,因为在此资源上不会发生冲突。
所以我的方法是在环境(Environment.SetEnvironmentVariable)中创建一个名为“CLIPBOARD_INUSE”的控制变量,并在特定线程需要执行ClipBoard方法时将其设置为true。 在其他线程中,一个while循环检查变量“CLIPBOARD_INUSE”是否为false(资源可用)(在再次检查之前使用Thread.Sleep())。 当第一个线程完成使用ClipBoard时,通过将我们创建的控制变量设置回false来释放资源,以便需要ClipBoard的下一个线程可以使用它。
希望您像我一样发现这个解决方案有用。
敬礼,
布鲁诺·科斯塔。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接