在一个线程中调用Invoke/BeginInvoke函数

4
我有一个使用了包含线程的类的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";
    }
}

这显然与使用后台线程的 Microsoft API 方法相反,例如 System.Timers.Timer 和 System.Io.Ports.SerialPort。这种方法有什么本质上的问题吗?它在某些方面是危险的吗?
谢谢, PaulH
编辑:另外,如果窗体没有立即订阅事件会怎样?它会用窗体不感兴趣的事件堵塞窗体的消息队列吗?
1个回答

3

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

从概念上看,没有任何问题。

计时器更加优雅地完成这样的任务。不过,如果计时器的间隔为10毫秒会减慢GUI的速度,这可能是为什么使用了Invoke的原因。

您不需要调用InvokeRequired,因为很明显控件在另一个线程中。此外,只有当您想异步调用方法时才需要调用BeginInvoke,而这在这里显然不是这种情况。

关于您的编辑:

不,消息队列不会被堵塞。如果没有注册处理程序,就不会触发任何事件。再仔细看一下您的代码 ;)


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