1、概述异步
在应用程序中,线程能够被看作是应用程序的一个较小的执行单位。每一个应用程序都至少拥有一个线程,咱们称为主线程。当调用和操做主线程的时候,该操做将动做添加到一个队列中,每一个操做均按照将它们添加到队列中的顺序连续执行,可是能够经过为这些动做指定优先级来影响执行顺序,而负责管理此队列的对象称之为线程调度程序。函数
咱们知道,WPF程序中,控件是属于UI线程的,若是试图在子线程中访问或者更新UI,就须要在子线程中通知主线程来处理UI, 经过向主线程的Dispatcher队列注册工做项,来通知UI线程更新结果。this
Dispatcher提供两个注册工做项的方法:Invoke 和 BeginInvoke。spa
这两个方法均调度一个委托来执行。Invoke 是同步调用,也就是说,直到 UI 线程实际执行完该委托它才返回。BeginInvoke是异步的,将当即返回。线程
代码片断以下:code
this.Dispatcher.BeginInvoke((Action)delegate() { 更新UI控件ing;
});
2、MVVMLight模式下ViewModel中更新UIcomponent
一般状况下,ViewModel 不从 DispatcherObject 继承,不能访问 Dispatcher 属性。这时候,咱们须要使用DispatcherHelper 组件来更新UI。对象
实际上,该类所作的是将主线程的调度程序保存在静态属性中,并公开一些实用的方法,以便经过统一的方式访问。blog
为了实现正常功能,须要在主线程上初始化该类。继承
一般,在 MVVM Light 应用程序中,DispatcherHelper 能够在 App.xaml.cs 或者ViewModel的构造函数中进行初始化,App.xaml.cs 是定义应用程序启动类的文件。
在 WPF 中,该类通常是在 App 构造函数中进行初始化的。
DispatcherHelper组件初始化之后,DispatcherHelper 类的 UIDispatcher 属性包含对主线程的调度程序的引用。
可是通常不多直接使用该属性,虽然确实可使用。一般咱们会使用 CheckBeginInvokeOnUi 方法来更新UI。
代码片断以下:
using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using GalaSoft.MvvmLight.Threading; using MvvmLightClosableTabControl.Models; using MvvmLightClosableTabControl.Pages; using System; using System.Collections.ObjectModel; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Threading; namespace MvvmLightClosableTabControl.ViewModel { public class MainViewModel : ViewModelBase { private ObservableCollection<TabItemModel> tabItemsList = new ObservableCollection<TabItemModel>() { new TabItemModel(){ Img="\\MvvmLightClosableTabControl;component\\Img\\1.png",Uri="\\Pages\\Page1.xaml",IsSelected=true , Header="TabItem1" }, new TabItemModel(){ Img="\\MvvmLightClosableTabControl;component\\Img\\2.png",Uri="\\Pages\\Page2.xaml",IsSelected=false, Header="TabItem2" }, new TabItemModel(){ Img="\\MvvmLightClosableTabControl;component\\Img\\3.png",Uri="\\Pages\\Page3.xaml",IsSelected=false, Header="TabItem3" }, new TabItemModel(){ Img="\\MvvmLightClosableTabControl;component\\Img\\4.png",Uri="\\Pages\\Page4.xaml",IsSelected=false, Header="TabItem4" }, }; public ObservableCollection<TabItemModel> TabItemsList { get { return tabItemsList; } set { tabItemsList = value; RaisePropertyChanged(() => TabItemsList); } } public MainViewModel() { DispatcherHelper.Initialize(); } #region Command private RelayCommand closeCurrentTabItemCommand; public RelayCommand CloseCurrentTabItemCommand { get { if (closeCurrentTabItemCommand == null) { closeCurrentTabItemCommand = new RelayCommand(CloseCurrentTabItemImpl); } return closeCurrentTabItemCommand; } set { closeCurrentTabItemCommand = value; } } private void CloseCurrentTabItemImpl() { foreach(var item in TabItemsList) { if(item.IsSelected == true) { TabItemsList.Remove(item); break; } } } //传递一个字符串参数的命令 private RelayCommand<string> addPageCommand; public RelayCommand<string> AddPageCommand { get { if (addPageCommand == null) { addPageCommand = new RelayCommand<string>(AddPage); } return addPageCommand; } set { addPageCommand = value; } } private void AddPage(string page) { try { TabItemModel myTabItemModel = new TabItemModel() { Img = $"\\MvvmLightClosableTabControl;component\\Img\\{page[4]}.png", Uri = $"\\Pages\\{page}.xaml", IsSelected = true, Header = page }; Task.Run( () => DispatcherHelper.CheckBeginInvokeOnUI( () => { TabItemsList.Add(myTabItemModel); } ));//故意在子线程中添加,为了使用DispatcherHelper,在子线程中访问UI } catch (AggregateException err) { foreach (var iem in err.InnerExceptions) { string msg = $"{iem.GetType()}{iem.Source}{iem.Message}"; MessageBox.Show(msg); } } } //传递事件参数的命令 private RelayCommand<MouseButtonEventArgs> tabItemMouseDoubleClickCommand; public RelayCommand<MouseButtonEventArgs> TabItemMouseDoubleClickCommand { get { if (tabItemMouseDoubleClickCommand == null) { tabItemMouseDoubleClickCommand = new RelayCommand<MouseButtonEventArgs>(TabItemMouseDoubleClickImpl); } return tabItemMouseDoubleClickCommand; } set { tabItemMouseDoubleClickCommand = value; } } private int _clickCnt = 0; private void TabItemMouseDoubleClickImpl(MouseButtonEventArgs e) { _clickCnt += 1; DispatcherTimer timer = new DispatcherTimer(); timer.Interval = new TimeSpan(0, 0, 0, 0, 300); timer.Tick += (s, e1) => { timer.IsEnabled = false; _clickCnt = 0; }; timer.IsEnabled = true; if (_clickCnt %2 == 0) { foreach (var item in TabItemsList) { if (item.IsSelected == true) { TabItemsList.Remove(item); PageWindow win = new PageWindow(); win.frm.Source = new System.Uri(item.Uri, UriKind.Relative); win.Title = item.Header; win.Show(); break; } } } } #endregion } }