【问题标题】:Calling Invoke/BeginInvoke from a thread从线程调用 Invoke/BeginInvoke
【发布时间】:2010-12-01 18:11:30
【问题描述】:

我有一个 C# 2.0 应用程序,其表单使用包含线程的类。

在线程函数中,不是直接调用事件处理程序,而是调用它。效果是拥有的表单不需要调用 InvokeRequired/BeginInvoke 来更新其控件。

public class Foo
{
    private Control owner_;
    Thread thread_;

    public event EventHandler<EventArgs> FooEvent;

    public Foo(Control owner)
    {
        owner_ = owner;
        thread_ = new Thread(FooThread);
        thread_.Start();
    }

    private void FooThread()
    {
        Thread.Sleep(1000);
        for (;;)
        {
            // Invoke performed in the thread
            owner_.Invoke((EventHandler<EventArgs>)InternalFooEvent, 
                new object[] { this, new EventArgs() });
            Thread.Sleep(10);
        }
    }

    private void InternalFooEvent(object sender, EventArgs e)
    {
        EventHandler<EventArgs> evt = FooEvent;
        if (evt != null)
            evt(sender, e);
    }
}

public partial class Form1 : Form
{
    private Foo foo_;

    public Form1()
    {
        InitializeComponent();

        foo_ = new Foo(this);
        foo_.FooEvent += OnFooEvent;
    }

    private void OnFooEvent(object sender, EventArgs e)
    {
        // does not need to call InvokeRequired/BeginInvoke() 
        label_.Text = "hello";
    }
}

这显然与使用 System.Timers.Timer 和 System.Io.Ports.SerialPort 等后台线程的 Microsoft API 使用的方法相反。这种方法有什么本质上的错误吗?有什么危险吗?

谢谢, 保罗H


编辑:另外,如果表单没有立即订阅事件怎么办?表单不感兴趣的事件是否会阻塞表单的消息队列?

【问题讨论】:

    标签: c# .net multithreading events invoke


    【解决方案1】:

    这是一个线程安全的调用,方法会在表单的线程中处理。

    从概念的角度来看它没有错。

    不过,计时器更适合此类任务。但是,可能是间隔为 10 毫秒的计时器会减慢 GUI,这可能就是使用 Invoke 的原因。

    您不需要调用 InvokeRequired,因为很明显 Control 位于另一个线程中。另外,BeginInvoke 只有在你想异步调用方法时才需要调用,这里显然不是这样。

    关于您的编辑: 不,消息队列不会被阻塞。如果没有注册处理程序,则不会触发任何事件。再看看你的代码;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 2010-11-24
      相关资源
      最近更新 更多