Control.Invoke делегатов в CF 3.5 - PullRequest
1 голос
/ 03 ноября 2011

Кажется, что все заметили, что CF не может Control.Invoke делегатов, кроме типа EventHandler. Я нашел несколько способов обойти проблему и поймать аргументы через сложные события и свойства, но это работает только для определенных объектов / примитивов.

Проблема в том, что когда я пытаюсь отправить элемент управления, программа выдает исключение во время выполнения: «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);
    }

}

Я пытался сделать это практически всеми возможными способами, и я всегда получал один и тот же результат.

Что я делаю не так? ----> есть "возврат"; потерян после Invoke.

В любом случае, фактическая ошибка в моем приложении (приведенный выше пример) заключается в следующей процедуре:

        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;
        }
    }

Основное различие в Invoke, я отправляю элемент управления из другого потока.

Не могли бы вы мне сказать, в чем разница? Почему это не работает?

1 Ответ

2 голосов
/ 03 ноября 2011

Вопрос прост. Ваш modifier_Modify вызов вызывает Invoke правильно, но затем он не завершается, он продолжает работу вниз и вызывает Controls.Add в контексте потока сразу после блока if (на самом деле Controls.Add будет вызван дважды, если исключение не было не бывает). Вставьте return сразу после вызова this.Invoke внутри блока if.

...