Нужно установить более одного свойства во время Control.Invoke - PullRequest
1 голос
/ 24 августа 2009

Я искал stackoverflow для способов перенаправления данных из потока в поток пользовательского интерфейса и нашел различные способы сделать это в 3.5.

Одно из самых элегантных решений для меня; хотя я все еще изучаю лямбды и замыкания, это решение Control.Invoke с входными параметрами .

Я не совсем понимаю код, но я понимаю, как его использовать, и он не совсем решает мою проблему.

Я хотел бы вызвать invoke и передать строку другому методу (DisplayStatusUpdate (msg)). Любые указатели будут оценены.

    private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e)
    {
        DisplayStatusUpdate(e.LoggingEvent.RenderedMessage);
    }

    private void DisplayStatusUpdate(string text)
    {
         _StatusTextBox.Text = _StatusTextBox.Text + text;
         _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
         _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
         _StatusTextBox.ScrollToCaret();
    }

Ответы [ 2 ]

5 голосов
/ 24 августа 2009

Вы можете сделать это с любым количеством параметров, например:

private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e)
{
    DisplayStatusUpdate(e.LoggingEvent.RenderedMessage);
}

private delegate void DisplayStatusUpdateDelegate(string text);

private void DisplayStatusUpdate(string text)
{
     if(InvokeRequired)
         this.Invoke(new DisplayStatusUpdateDelegate(DisplayStatusUpdate), text);
     else
     {
         _StatusTextBox.Text = _StatusTextBox.Text + text;
         _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
         _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
         _StatusTextBox.ScrollToCaret();
     }
}

Есть еще один метод, который я использовал в текущем проекте, который может значительно сократить код. Подробности здесь .

Если вы реализуете этот метод, вам потребуется:

Создание формы с использованием фабрики AOP:

Form f = AOPFactory.Create<Form1>();
Application.Run(f);

А затем вы просто украшаете обработчик событий атрибутом [RunInUIThread]. Он использует модель перехвата метода Касла для автоматического вызова при необходимости.

Таким образом, приведенный выше код становится:

private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e)
{
    _StatusTextBox.Text = _StatusTextBox.Text + text;
    _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
    _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
    _StatusTextBox.ScrollToCaret();
}

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

2 голосов
/ 24 августа 2009

Если вы используете C # 3.5 (или более позднюю версию), вы можете использовать захваченные переменные, которые могут упростить код:

private void DisplayStatusUpdate(string text)
{
    this.Invoke(new MethodInvoker(() => 
    {
         _StatusTextBox.Text = _StatusTextBox.Text + text;
         _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
         _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
         _StatusTextBox.ScrollToCaret();
    }));
}

То, что компилятор сделает за кулисами, - это создать класс для хранения текста, создать делегат MethodInvoker и передать этот делегат и экземпляр сгенерированного класса в Invoke метод. В вышеупомянутой схеме это, конечно, сделает ненужную работу по созданию делегата и вызову Invoke, даже если код уже выполняется в том же потоке; но я считаю, что такой метод не следует вызывать так часто, чтобы это было проблемой производительности.

Если вы хотите, вы можете заменить использование MethodInvoker делегатом без параметра Action или любым другим делегатом без параметра, который возвращает void.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...