blocked UI in MVVM
本文关键字:MVVM in UI blocked | 更新日期: 2023-09-27 17:51:11
我正在尝试构建一个应用程序,遵循MVVM策略。不幸的是,我的原始示例(请参见下文)阻塞了UI,尽管我特别调用了dispatcher。不知道为什么…有什么建议吗?
class ViewModel : INotifyPropertyChanged
{
private readonly Dispatcher _dispatcher;
private string _name;
public ViewModel()
{
_dispatcher = Dispatcher.CurrentDispatcher;
}
public string Name
{
get { return _name; }
set
{
_name = value;
InvokePropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void InvokePropertyChanged(string propertyName)
{
var e = new PropertyChangedEventArgs(propertyName);
PropertyChangedEventHandler changed = PropertyChanged;
if (changed != null)
changed(this, e);
}
public void send()
{
Action dispAc = () => NameAsync();
_dispatcher.BeginInvoke(dispAc);
}
private void NameAsync()
{
Name = "name1";
Thread.Sleep(5000);
}
}
p。第一个回复澄清了一个问题,谢谢。对于那些不使用4.5的人,我使用
Task.Factory.StartNew(dispatchAction);
此任务不使用Dispatcher.CurrentDispatcher
。Dispatcher.CurrentDispatcher
显示当前正在执行的线程,可能是UI线程。这意味着,NameAsync()
函数在UI线程中被调用,当然仍然阻塞UI。你可以使用Task.Run()异步执行你的方法,以避免阻塞UI:
Action dispAc = () => NameAsync();
Task.Run(dispAc);
你正在分派…UI线程。在另一个线程上完成你的工作,然后,当你完成后,将UI更新分派到UI线程上。
你甚至不需要。
只要你不是3.0的框架,绑定将自动封送INPC PropertyChanged
事件到UI线程。因此,当你从工作线程中接触这些属性时,你可以省去任何调度。
用你的例子…
public void send()
{
// We're on the UI thread here
Task.Run(() => NameAsync());
}
private void NameAsync()
{
// we're on some anonymous threadpool thread right now
Name = "name1";
// the event is fired on the threadpool, but bindings automatically marshall
// UI update code onto the UI thread, so it returns directly before UI is
// changed
Thread.Sleep(5000);
// and now our threadpool thread is sleeping. Good night, sweet prince.
}
改变这个,
public void send()
{
Action dispAc = () => NameAsync();
_dispatcher.BeginInvoke(dispAc);
}
到this
public void send()
{
Action dispAc = () => NameAsync();
_dispatcher.BeginInvoke(dispAc, DispatcherPriority.Background);
}
如果你真的不需要UI thread
来执行需要Dispatcher
的方法,那么就使用TPL
。
默认情况下,如果你没有指定DispatcherPriority
,它将使用Normal
,所以它将使用任何当前线程,这可能占用UI Thread
,例如,当它试图为其他控件做一些Render
时。
.NET 4.5
,可以考虑使用await
和async
关键字。如果没有,那么就像其他人建议的那样,只是生成一个不同的线程来更新UI
。与Silverlight
或WinRT
相比,WPF
的Dispatcher
足够智能,可以将UI
的更新编组到主线程。