如何在多个线程之间进行通信? [英] How do I communicate between multiple threads?

查看:76
本文介绍了如何在多个线程之间进行通信?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为另一个程序编写插件,该程序使用本机程序打开一系列文件以从中提取一些数据.我遇到的一个问题是这个过程需要很长时间,我想防止用户界面挂起.另外,我还想让用户能够在完成之前取消该过程.过去,我曾使用后台工作人员处理此类事情,但在这种情况下,我认为 BackgroundWorker 行不通.

I'm writing a plug-in for another program which uses the native program to open a series of files to extract some data from. One problem I am having is the process takes a long time and I want to keep the user interface from hanging. Plus I also want to give the user the ability to cancel the process before it completes. In the past I've used a background worker for this type of thing, but in this case I don't think a BackgroundWorker will work.

要通过我使用的 API 创建插件,可以通过从 IAPICommand 接口继承来创建自定义命令.该接口包括一个 Execute(Application app) 方法.然后类被实例化,当用户在程序中调用自定义命令时,程序会调用 Execute() 方法.

To create a plug-in through the API I am using one can create a custom command by inheriting from an IAPICommand interface. This interface includes an Execute(Application app) method. The class is then instantiated and the Execute() method is called by the program when the user evokes the custom command in the program.

Execute() 方法在调用时被传递一个对当前 Application 对象的引用,正是这个应用程序对象用于打开文件以从中提取数据.但是,当原始 Execute() 线程以外的线程请求时,应用程序实例无法打开文档.

The Execute() method is passed a reference to the current Application object when it is called, and it is this application object that is used to open the files to extract data from. However, the application instance is not able to open a document when requested by a thread other the the original Execute() thread.

因此通常 UI 将存在于主线程上,而耗时的数据提取将在辅助线程上执行.但是,在这种情况下,数据提取必须在主线程上进行,我需要为UI创建一个辅助线程.

So typically the UI would exist on the main thread, and the time consuming data extraction would be performed on a secondary thread. However, in this case the data extraction must be performed on the main thread, and I need to create a secondary thread for the UI.

这是代码的精简版.

class MyCommand:IAPICommand
{
    public void Execute(Application app) // method from IAPICommand
    {
        Thread threadTwo= new Thread(ShowFormMethod);
        threadTwo.Start();
    }

    public void ProcessWidget(Widget w, Application app)
    { 
        //uses an App to work some magic on C
        //app must be called from the original thread that called ExecuteCommand()
    }

    //method to open custom form on a seperatethread
    public void ShowFormMethod()
    {
      MyForm form = new MyForm();
      form.ShowDialog();  
    }
}

这是一个流程图,显示了我认为这最终应该如何工作.

Here is a flow chart that shows how I think this should ultimately work.

替代文字 http://dl.dropbox.com/u/113068/SOMLibThreadingDiagram.jpg

  1. 这张图是否有意义?如果有,我是否采取了正确的方法来解决这个问题?
  2. 一旦主线程启动 UI 线程,我希望它等待用户选择要处理的小部件,或者通过关闭表单(图中的红色数字)来结束命令.如何让主线程等待,以及如何触发它继续处理或在 UI 线程结束时继续结束?我在想我可以让主线程等待监视器锁.然后 UI 线程会填充要处理的 Widget 的静态列表,然后脉冲主​​线程以触发处理.当表单关闭时,UI 线程也会对主线程进行脉冲,如果要处理的小部件列表为空时主线程被脉冲,主线程就会知道继续到命令的末尾.
  3. 如何让主线程将小部件处理的进度或完成情况传达回 UI 线程(图中的黄色箭头)?我是否只是使用 Form 的 BeginInvoke() 方法来执行此操作?
  4. 如何允许 UI 线程取消小部件处理(图中的绿色箭头)?我想我可以设置一个静态布尔标志,在处理每个小部件之前检查该标志?

推荐答案

在您的应用程序中使用多个线程来创建表单通常是一个坏主意.完成这项工作并非不可能,但它比您想象的要困难得多,因为处于父子关系中的表单会相互发送消息,当它们发送消息时,发送消息的表单会阻塞,直到接收处理它.

It's generally a bad idea to have multiple threads in your application that each create forms. It isn't impossible to make this work, but it's much harder than you think it will be because forms that are in a parent-child relationship send messages to each other, and when they do, the one sending the message blocks until the one receiving handles it.

将此与您明确执行的线程之间的消息传递或同步混合在一起,很容易导致死锁.因此,一般来说,最好确保为用户界面保留主线程,并在没有 UI 的其他线程中进行所有处理.

Mix this in with the message passing or synchronization between threads that you are doing explicitly, and it's easy to end up with deadlocks. So, in general, you are better off making sure that you reserve your main thread for your user interface, and do all processing in other threads that have no UI.

如果您符合该设计,则后台线程可以使用 Control.BeginInvoke 将消息传递给 UI 线程,而无需等待消息被处理.

If you conform to that design, then the background threads can use Control.BeginInvoke to pass messages to the UI thread without having to wait for the messages to be processed.

这篇关于如何在多个线程之间进行通信?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆