Фоновые и пользовательские потоки в приложении WPF - PullRequest
1 голос
/ 22 сентября 2010

Я читаю Шаблон DataModel-View-ViewModel: 2

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

[Conditional("Debug")]
protected void VerifyCalledOnUIThread()
{
    Debug.Assert(Dispatcher.CurrentDispatcher == this.Dispatcher,
        "Call must be made on UI thread.");
}

на самом деле ничего не делает, например. установить значения. Так что, если я не буду отлаживать, он вообще что-нибудь сделает?

Ответы [ 3 ]

4 голосов
/ 22 сентября 2010

Я не совсем понимаю, нужно ли мне проверять пользовательский интерфейс или фоновый поток.Что делать, если я пропускаю проверки.

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

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

Такжекод ниже ... на самом деле ничего не делает, например.установить значения.Так что, если я не буду отлаживать, он вообще что-нибудь сделает?

При компиляции сборки выпуска Debug.Assert (и ваш метод VerifyCalledOnUIThread) даже не появятся в коде, так что нет,ничего не случится.

2 голосов
/ 23 сентября 2010

Извините, но я не согласен с Крисом Шмичем.

Вы можете видеть, что VerifyCalledOnUIThread() появляется в DataModel. На самом деле цель - Для проверки DataModel (не элемента управления), доступ к которому возможен только из потока пользовательского интерфейса . Да, пользовательский интерфейс WPF / SilverLight не защищен от многопотоковых операций, но в данном случае это не было реальной причиной.

Дело в том, что если вы связываете что-то (datamodel / viewmodel) с пользовательским интерфейсом WPF / SilverLight и получаете доступ к нему из другого потока, отличного от потока пользовательского интерфейса, то вы получите неинформативное исключение. Устранение неполадок, связанных с этой ошибкой, очень сложно, потому что исключение не дает никакой подсказки.

Я приведу вам пример об этом:

//pass model to datacontex and bind it 
mycontrol.DataContext = myModel;

//myThreadedService is an assynchronous service
//done ini different thread.
//so ServiceDone will call myModel.Complete from different thread
//system will crash unexpectedly without enough clue
myThreadedService.ServiceDone += (s, e) => { myModel.Complete = true; }
myThreadedService.CallService();

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

Debug.Assert(Dispatcher.CurrentDispatcher == this.Dispatcher,
        "Call must be made on UI thread.");

Этот код даст подсказку, когда вы обращаетесь к DataModel из другого потока.

2 голосов
/ 22 сентября 2010

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

Некоторые обратные вызовы асинхронных операций, такие как вызов веб-службы / wcf, обрабатываются в потоке пользовательского интерфейса.Кроме того, если вы используете таймер, такой как DispatchTimer, он также находится в потоке пользовательского интерфейса.Наконец, если вы используете поток BackgroundWorker, он также обрабатывается в потоке пользовательского интерфейса.

Надеюсь, это поможет.

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