CF 3.5 中的 Control.Invoke 委托

发布于 2024-12-13 12:55:24 字数 2408 浏览 1 评论 0原文

似乎每个人都注意到 CF 无法 Control.Invoke 除 EventHandler 类型之外的委托。我找到了几种方法来解决该问题并通过棘手的事件和属性捕获参数,但它仅适用于某些对象/基元。

问题是当我尝试发送 Control 时,程序在执行时抛出异常:“Control.Invoke 必须用于与在单独线程上创建的控件进行交互”,无论我检查 Control.IsInvokeRequired 并由处理程序槽跟踪Invoke 方法...见鬼,有一个片段:

    static class Program
{
    [MTAThread]
    static void Main()
    {
        Form1 frm = new Form1();
        frm.modifier = new CModifier(ref frm);
        Application.Run(frm);
    }
 }

class CModifier
{
    internal event EventHandler Modify;

    internal CModifier(ref Form1 _frm)
    { frm = _frm; }

    private Form1 frm;

    internal void Start()
    {
        Thread t = new Thread(new ThreadStart(TestMe));
        t.Start();
    }
    private void TestMe()
    {
        frm._current = new Label() { Text = "Try Me" };
        Modify(this, EventArgs.Empty);
    }

}

public partial class Form1 : Form
{
    internal Form1()
    {
        InitializeComponent();
    }

    internal CModifier modifier;
    internal Control _current;

    private void Form1_Load(object sender, EventArgs e)
    {
        modifier.Modify += new EventHandler(modifier_Modify);
        modifier.Start();
    }

    void modifier_Modify(object sender, EventArgs e)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new EventHandler(modifier_Modify));
        }
        this.panel1.Controls.Add(_current);
    }

}

我尝试了几乎所有可能的方法,但总是得到相同的结果。

我做错了什么? ---->有一个“回报”;调用后丢失。

无论如何,我的应用程序的实际错误(上面只是一个示例)是在这个过程中:

        internal void ManageControls(RSSDecisionMaking.InterfaceBehaviour _behaviour, Control _control)
    {
        if (this.InvokeRequired)
        {
            this.Invoke((Action)delegate { ManageControls(_behaviour, _control); });
            return;
        }
        switch (_behaviour)
        {
            case RSSDecisionMaking.InterfaceBehaviour.Display:
                this.pnDisplayContainer.Controls.Clear();
                this.pnDisplayContainer.Controls.Add(_control);
                break;
            case RSSDecisionMaking.InterfaceBehaviour.Command:
                this.pnDisplayContainer.Controls.Clear();
                this.pnDisplayContainer.Controls.Add(_control);
                this.pnDisplayContainer.Controls[0].Focus();
                break;
        }
    }

主要区别在于调用内容,我从另一个线程发送一个控件。

能告诉我它有什么区别吗?为什么这不起作用?

It seems like everybody have noticed CF is unable to Control.Invoke delegates other than EventHandler type. I found few ways to workaround the problem and catch the arguments trough tricky events and properties, but it works just for certain objects/primitives.

The problem is when I try to send a Control, the program throws an exception at execution time: "Control.Invoke must be used to interact with controls created on a separate thread" no matters that I checked Control.IsInvokeRequired and tracked by handler trough the Invoke method...what hell, there is the snipet:

    static class Program
{
    [MTAThread]
    static void Main()
    {
        Form1 frm = new Form1();
        frm.modifier = new CModifier(ref frm);
        Application.Run(frm);
    }
 }

class CModifier
{
    internal event EventHandler Modify;

    internal CModifier(ref Form1 _frm)
    { frm = _frm; }

    private Form1 frm;

    internal void Start()
    {
        Thread t = new Thread(new ThreadStart(TestMe));
        t.Start();
    }
    private void TestMe()
    {
        frm._current = new Label() { Text = "Try Me" };
        Modify(this, EventArgs.Empty);
    }

}

public partial class Form1 : Form
{
    internal Form1()
    {
        InitializeComponent();
    }

    internal CModifier modifier;
    internal Control _current;

    private void Form1_Load(object sender, EventArgs e)
    {
        modifier.Modify += new EventHandler(modifier_Modify);
        modifier.Start();
    }

    void modifier_Modify(object sender, EventArgs e)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new EventHandler(modifier_Modify));
        }
        this.panel1.Controls.Add(_current);
    }

}

I tried to do in almost every way possible and I always get the same result.

What am I doing wrong? ----> there is a "return;" lost after Invoke.

Anyway, te actual error at my app (above is just an example) is in this procedure:

        internal void ManageControls(RSSDecisionMaking.InterfaceBehaviour _behaviour, Control _control)
    {
        if (this.InvokeRequired)
        {
            this.Invoke((Action)delegate { ManageControls(_behaviour, _control); });
            return;
        }
        switch (_behaviour)
        {
            case RSSDecisionMaking.InterfaceBehaviour.Display:
                this.pnDisplayContainer.Controls.Clear();
                this.pnDisplayContainer.Controls.Add(_control);
                break;
            case RSSDecisionMaking.InterfaceBehaviour.Command:
                this.pnDisplayContainer.Controls.Clear();
                this.pnDisplayContainer.Controls.Add(_control);
                this.pnDisplayContainer.Controls[0].Focus();
                break;
        }
    }

The main difference is in the Invoke stuff, I'm sending a Control from another thread.

Could tell me what the difference it makes? Why this does not work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

野生奥特曼 2024-12-20 12:55:24

问题很简单。您的 modifier_Modify 调用正确调用 Invoke,但随后它不会退出,而是继续向下并在 ifControls.Add code> 块(事实上,如果没有发生异常,Controls.Add 将被调用两次)。在 this.Invoke 调用之后的 if 块内插入一个 return

The issue is simple. Your modifier_Modify call calls Invoke properly, but then it doesn't exit, it continues down and calls Controls.Add in the thread context right after the if block (in fact Controls.Add would get called twice if the Exception didn't happen). Insert a return right after the this.Invoke call, inside the if block.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文