Проблемы с производительностью при обновлении интерфейса без предварительной проверки InvokeRequired? - PullRequest
1 голос
/ 12 марта 2009

Я немного поленился (иногда это хорошо) и начал обновлять пользовательский интерфейс WinForms, вызывая обратный вызов без проверки InvokeRequired сначала.

Есть ли проблемы с производительностью или соображения, о которых мне следует знать?

    private delegate void SetStatusEventHandler(string statusMessage);
    private void SetStatus(string statusMessage)
    {
        Invoke((MethodInvoker) (() =>
        {
            resultLabel.Text = statusMessage;
        }));

        //  - vs -

        if (InvokeRequired)
        {
            SetStatusEventHandler cb = SetStatus;
            Invoke(cb, statusMessage);
        }
        else
        {
            resultLabel.Text = statusMessage;
        }
    }

[EDIT] : В большинстве случаев метод, вызывающий «invoke», будет вызываться не более, например, 10–20 раз в секунду с большим интервалом между ними.

[ОБНОВЛЕНИЕ] Устанавливается следующим методом расширения

public static class SmartInvoker
{
    public static void InvokeHandler(this Control control, MethodInvoker del)
    {
        if (control.InvokeRequired)
        {
            control.Invoke(del);
            return;
        }
        del();
    }
}

...

    private void SetStatus(string statusMessage)
    {
        this.InvokeHandler(() => resultLabel.Text = statusMessage);
    }

Полагаю, еще одна тема, в которую мне нужно углубиться, - это узнать, как управлять классами методов расширения. Спасибо за вашу помощь

Ответы [ 3 ]

3 голосов
/ 12 марта 2009

Почему бы просто не добавить метод расширения, чтобы вам больше не приходилось об этом думать?

public static object SmartInvoke(this Control control, MethodInvoker del) {
  if ( control.InvokeRequired ) {
    control.Invoke(del);
    return;
  }
  del();
}

Теперь ваш код становится

private void SetStatus(string statusMessage) {
  this.SmartInvoke(() => resultLabel.Text = statusMessage);
}
3 голосов
/ 12 марта 2009

РЕДАКТИРОВАТЬ: см. Комментарии для обсуждения всей публикации против немедленной отправки малярии.

В любом случае, мой ответ на самом деле один и тот же: если только это не происходит в огромной степени часто без необходимости (то есть большую часть времени вы находитесь в потоке пользовательского интерфейса, и он привязан к чему-то вроде обработчик движения мыши) я бы не переживал. Это, безусловно, делает код проще. Если это будет вызываться очень часто, я бы измерил и протестировал больше:)

Invoke быстрее с делегатом EventHandler или MethodInvoker, чем с другими. Я не знаю, есть ли какая-то разница между ними - вы можете проверить.

Вы можете сделать это еще проще, написав метод расширения, например,

public static void InvokeHandler(this Control control, MethodInvoker handler)
{
     control.Invoke(handler);
}

Тогда вы можете сделать свой код:

private void SetStatus(string statusMessage)
{
    this.InvokeHandler(delegate
    {
        resultLabel.Text = statusMessage;
    });
}

или

private void SetStatus(string statusMessage)
{
    InvokeHandler(() => resultLabel.Text = statusMessage);
}

Таким образом, вам не нужно указывать тип делегата.

0 голосов
/ 12 марта 2009

Я считаю, что это просто предотвращает ненужный пост, если вы уже в той же теме. Так что, если это будет наиболее распространенный сценарий (нахождение в правильном потоке), это может привести к небольшому снижению производительности, если не проверять, но я не верю, что это действительно требуется.

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