Замена InvokeRequired в WPF

17 Май
2011

Многие, кто занимается многопоточным программированием в Win.Forms, должны хорошо знать, что, для изменения состояния какого либо контрола из потока его — контрол — не создававшего , обязательно должно проверяться свойство контрола InvokeRequired. Код ниже, который может смутить новичков, несомненно давно уже отложился в памяти программистов неоднократно имевших дело с потоками:

Представим, что на форме есть Label, текст в котором должен периодически обновляться из другого потока. Так вот примерно следующим образом будет выглядеть функция для обновления:

delegate void UpdateLabelDelegate(string msg);

public void displayMessage(string Msg)
        {
            if (msgResceipient != null)
            {
                if (!msgResceipient.InvokeRequired)
                {
                   msgResceipient.Text = Msg;
                }
                else
                {
                    UpdateLabelDelegate d = new UpdateLabelDelegate(displayMessage);
                    this.Invoke(d, new object[] { msgResceipient, Msg });
                }
            }
        }

Но вот для WPF приложений такой код не подойдет. В принципе сама конструкция остается практически без изменений, но используемые методы изменяются примерно следующим образом:

delegate void UpdateLabelDelegate(string msg);

public void displayMessage(string Msg)
        {
            if (msgResceipient != null)
            {
                if (msgResceipient.Dispatcher.CheckAccess())
                {
                   msgResceipient.Content= Msg ;
                }
                else
                {
                showMessageDelegate d = new showMessageDelegate(displayMessage);
                msgResceipient.Dispatcher.BeginInvoke(d,
                    new object[] { msgResceipient, Msg });
                }
            }
        }

Кстати, можете не искать Dispatcher.CheckAccess() в IntelliSense — его там нет. Разработчики по непонятным причинам не стали его туда включать… Тем не менее компилятор при использовании этого метода ругаться не будет.

Надеюсь кому то эта информация поможет.
Извините, если баян, но когда мне это было нужно, я так и не смог найти в рунете ответ 😉

Кстати, если вам известна более хорошая техника многопоточного программирования для WPF, а тем более, если есть хороший пример того как увязать databinding с многопоточностью, буду рад увидеть ссылки (надеюсь спам бот их не порежет) 🙂

2leep.com

2 комментария к записи Замена InvokeRequired в WPF

Avatar

serg

12th Июнь 2012 в 11:07

delegate void ActionHandler();
void post(ActionHandler action) {
if (this.InvokeRequired) this.BeginInvoke(action); else action();
// if (this.Dispatcher.CheckAccess()) action(); else this.Dispatcher.BeginInvoke(action);
}

public void selLabel(string text) {
post(()=>{ myLabel.Text=text; });
}

Avatar

sweetpain

20th Апрель 2015 в 15:41

Спасибо, дорогой далекий друг! Твоя мини-статья оказалась полезной

Оставить комментарий или два

*

Наверх