使用 COM 互操作在 SQL 查询期间实现响应式 UI 的 C# 最佳方法
我正在为用 VB6 编写的 EXE 制作一个 C# DLL 插件。我无法访问 EXE 的源代码。 DLL 本身可以正常工作并与 EXE 进行良好的通信。
以下是事件的处理过程:
- 用户在 EXE 上发出命令,然后调用 DLL 中的函数,传递一个对象作为参数
- DLL 处理数据,有时需要很长时间
DLL 通过调用对象的函数来响应那已经通过了。 DLL函数本身不返回任何内容
public void DoCommand(object CommandSettings) { //ObjectVB6 是我的自定义类,可以轻松调用 COM 方法和属性 ObjectVB6 CS = new ObjectVB6(CommandSettings); ... //处理数据 CS.CallMethod("MyReply", args); }
我的问题是,在长时间查询(来自 DLL)期间,EXE 的 UI 冻结。
防止这种情况的最佳方法是什么?我尝试过使用异步 MySQL 查询,但效果不佳,还尝试过使用多线程,但这只会遇到受保护的内存问题。
您能提供的任何建议都会很棒。几天来一直试图解决这个问题。谢谢。
I am making a C# DLL plugin for a EXE written in VB6. I do not have access to the source of the EXE. The DLL itself works and communicates fine with the EXE.
Here is the process for a event:
- User issues command on EXE which then calls a function in the DLL, passing an object as a parameter
- DLL processes data which sometimes takes a long time
The DLL responds by calling a function of the object that was passed. The DLL function itself does not return anything
public void DoCommand(object CommandSettings) { //ObjectVB6 is my custom class to allow easy calling of COM methods and properties ObjectVB6 CS = new ObjectVB6(CommandSettings); ... //process data CS.CallMethod("MyReply", args); }
My problem is that during long queries (from the DLL), the EXE's UI freezes.
What is the best way to prevent this? I have tried using asynchronous MySQL queries, which were no good, and tried using multiple threads, which just run into protected memory issues.
Any advice you can provide would be awesome. Been trying to address this issue for days. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
尝试以下操作:
正如一位响应者所说,由于 VB6 单元线程的性质,这可能会也可能不会起作用。
Try the following:
Like one of the responders said, this may or may not work due to the nature of VB6 apartment threading.
为什么不能只使用工作线程来执行该代码?您遇到了什么“受保护的内存问题”?
Why can't you just use a worker thread for that code? What "protected memory issues" are you running into?
IMO 处理此问题的最佳方法是将您的请求放入
ThreadPool
在 DLL 端,“即发即忘”风格。你试过这个吗?否则,您将不得不为 VB6 程序设置一个回调函数来获取状态,正如您可能已经发现的那样,由于 VB6 的单线程单元模型,这很棘手。
如果您想更深入地探索 VB6 中多线程的风险和回报,请查看以下文章。它可能允许您简单地启动一个线程并在 VB6 端执行此操作:
VB5 和 VB6 中的多线程
http://www.freevbcode.com/ShowCode.Asp?ID=1287
IMO the best way to deal with this is to throw your request into the
ThreadPool
on the DLL side, "fire and forget" style. Have you tried this?Otherwise you'll have to jigger up a callback function to your VB6 program to get status, which, as you may have already found out, is tricky due to VB6's Single-Threaded Apartment model.
If you want to explore the perils and rewards of multi-threading in VB6 in greater depth, have a look at the following article. It may allow you do simply start up a thread and do it on the VB6 side:
Multi-Threading In VB5 and VB6
http://www.freevbcode.com/ShowCode.Asp?ID=1287
.NET 中开发的所有函数都可以使用委托异步调用,然后调用 BeginInvoke 来实际调用该函数。由于您的函数不返回任何内容,因此您无需调用 EndInvoke。通过使用 IAsyncResult 您可以满足您的回调要求。关于如何正确执行此操作的一个很好的参考是 O'Reilly 出版的 Juval Lowy 所著的“Programming .NET Components”。 ISBN 是 0596102070。祝你好运。
All functions developed in .NET can be called asynchronously using a delegate and then calling BeginInvoke to actually call the function. Since your function does not return anything, you won't need to call EndInvoke. By making use of IAsyncResult you can meet your Callback requirement. A good reference for how to do this properly is "Programming .NET Components" by Juval Lowy published by O'Reilly. The ISBN is 0596102070. Good Luck.
我已经找到了一种方法来实现我所追求的目标。虽然我更喜欢更好的方法,但这种方法有效。
使用两个队列来共享信息。主线程监听 get _get 队列,并在发出请求时设置 _set 队列。工作线程简单地将请求插入_get队列,并等待直到_set准备好。主线程只是充当代理。
感谢您的帮助!
I've figured a way to accomplish what I was after. While I would prefer a nicer method, this way works.
Used two queues to share information. Main thread listens to get _get queue, and sets the _set queue when a request is made. Worker thread simple inserts request into _get queue, and waits until _set is ready. The main thread is just acting like a proxy.
Thanks for your help!