Dispatcher中Invoke与BeginInvoke
[同步]Invoke
Application.Current.Dispatcher.Invoke(AutoIncreaseNumber);
[异步]BeginInvoke
Application.Current.Dispatcher.BeginInvoke((Action)AutoIncreaseNumber);
两者都会阻塞UI线程
基于WPF4.5.1示例
Invoke 按钮对应的是InvokeCommand
BeginInvoke按钮对应的是BeginInvokeCommand
可以发现,在执行按钮的命令时,UI线程是会阻塞,计时器并不会走动
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds();
timer.Tick += timer_Tick;
timer.Start();
} void timer_Tick(object sender, EventArgs e)
{
Now = DateTime.Now;
} private DateTime now = DateTime.Now; public DateTime Now
{
get { return now; }
set
{
now = value;
RaisePropertyChanged("Now");
}
} private int number;
/// <summary>
/// 数值用于显示
/// </summary>
public int Number
{
get { return number; }
set
{
number = value;
RaisePropertyChanged("Number");
}
} private bool isIncrease;
/// <summary>
/// 是否可以自增长
/// </summary>
public bool IsIncrease
{
get { return isIncrease; }
set
{
isIncrease = value;
RaisePropertyChanged("IsIncrease");
}
} /// <summary>
/// 自动增长
/// </summary>
private void AutoIncreaseNumber()
{
IsIncrease = !isIncrease;
while (IsIncrease && Number < )
{
Number++;
}
} #region RelayCommands
/// <summary>
/// Invoke命令
/// </summary>
public RelayCommand InvokeCommand
{
get
{
return new RelayCommand(() =>
{
Application.Current.Dispatcher.Invoke(AutoIncreaseNumber);
});
}
}
/// <summary>
/// BeginInvoke命令
/// </summary>
public RelayCommand BeginInvokeCommand
{
get
{
return new RelayCommand(() =>
{
//这里直接使用匿名方法会报错
//'Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type'
//使用强制转换的方式
Application.Current.Dispatcher.BeginInvoke((Action)AutoIncreaseNumber);
});
}
}
/// <summary>
/// 清理数字命令
/// </summary>
public RelayCommand ClearCommand
{
get
{
return new RelayCommand(() =>
{
Number = ;
IsIncrease = false;
});
}
}
#endregion
}
注:其中阻塞UI线程的原因是把Number的递增放到了Dispather中去执行,如果想要不阻塞,那么需要有一个新的DispatcherTimer的对象去执行这个递增的逻辑,那么就不会阻塞UI线程了。
所以说这里所说的异步并不是相对于UI线程的异步,那么究竟是什么?
Invoke 是同步操作;因此,直到回调返回之后才会将控制权返回给调用对象。
BeginInvoke 是异步操作;因此,调用之后控制权会立即返回给调用对象。
--- msdn
做一个测试
/// <summary>
/// DiffInInvokeAndBeginInvoke.xaml 的交互逻辑
/// </summary>
public partial class DiffInInvokeAndBeginInvoke : Window
{
public DiffInInvokeAndBeginInvoke()
{
InitializeComponent();
this.ltb.ItemsSource = _infos;
this.Loaded += DiffInInvokeAndBeginInvoke_Loaded;
} private ObservableCollection<string> _infos = new ObservableCollection<string>(); private void DiffInInvokeAndBeginInvoke_Loaded(object sender, RoutedEventArgs e)
{
ExcuteMethod();
ExcuteMethod_2();
ExcuteMethod_3();
} private void ExcuteMethod()
{
Dispatcher.Invoke(new Action<string>(PrintInformation), System.Windows.Threading.DispatcherPriority.SystemIdle, "1-1: SystemIdle Invoke");
Dispatcher.Invoke(new Action<string>(PrintInformation), System.Windows.Threading.DispatcherPriority.Send, "1-2: Send Invoke ");
Dispatcher.BeginInvoke(new Action<string>(PrintInformation), System.Windows.Threading.DispatcherPriority.Normal, "1-3: Normal BeginInvoke");
Dispatcher.BeginInvoke(new Action<string>(PrintInformation), System.Windows.Threading.DispatcherPriority.Send, "1-4: Send BeginInvoke");
DispatcherOperation dop = Dispatcher.BeginInvoke(new Action<string>(PrintInformation), "1-5: Defaut BeginInvoke");
} private void ExcuteMethod_2()
{ Dispatcher.BeginInvoke(new Action<string>(PrintInformation), System.Windows.Threading.DispatcherPriority.Normal, "2-1: Normal BeginInvoke");
Dispatcher.Invoke(new Action<string>(PrintInformation), System.Windows.Threading.DispatcherPriority.Send, "2-2: Send Invoke ");
Dispatcher.BeginInvoke(new Action<string>(PrintInformation), System.Windows.Threading.DispatcherPriority.Send, "2-3: Send BeginInvoke");
} private void ExcuteMethod_3()
{
Dispatcher.Invoke(new Action<string>(PrintInformation), System.Windows.Threading.DispatcherPriority.Send, "3-1: Send Invoke ");
Dispatcher.BeginInvoke(new Action<string>(PrintInformation), System.Windows.Threading.DispatcherPriority.Send, "2-2: Send BeginInvoke");
} private void PrintInformation(string info)
{
_infos.Add(info);
}
}
结果如下:
从结果及MSDN对于Invoke及BeginInvoke的解释,很容易就理解了。
Invoke一定要执行完了才会执行下去,而BeginInvoke是没有等待执行完就接着往下走了,然后会根据线程的调用优先级开始执行。
Dispatcher中Invoke与BeginInvoke的更多相关文章
- .Net基础——程序集与CIL HttpClient封装方法 .Net Core 编码规范 C#中invoke和beginInvoke的使用 WebServeice 动态代理类
.Net基础——程序集与CIL 1. 程序集和CIL: 程序集是由.NET语言的编译器接受源代码文件产生的输出文件,通常分为 exe和dll两类,其中exe包含Main入口方法可以双击执行,dll ...
- C#中Invoke 和 BeginInvoke 的区别
Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托. Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句 ...
- C#中Invoke和BeginInvoke的区别
1.Invoke() 调用时,Invoke会阻止当前主线程的运行,等到 Invoke() 方法返回才继续执行后面的代码,表现出“同步”的概念. 2.BeginInvoke() 调用时,当前线程会启用线 ...
- WPF Invoke和BeginInvoke
在WPF中Invoke和BeginInvoke和Winform中的是差不多的,只是一个用Control的一个用Dispatcher的. 而Invoke和BeginInvoke的区别嘛 就是一个是同步的 ...
- [转载]Winform中Control的Invoke与BeginInvoke方法
转自http://www.cppblog.com/baby-fly/archive/2010/04/01/111245.html 一.为什么 Control类提供了 Invoke和 BeginInvo ...
- C#中的Invoke和BeginInvoke
一.Control#Invoke() 和Control#BeginInvoke() 在非UI线程中调用MessageBox.Show()结果是非模态对话框: 在UI线程中调用MessageBox.Sh ...
- 【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)
[分析]浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang) 今天无意中看到有关Invoke和BeginInvoke的一些资料,不太清楚它们之间 ...
- C#中Control的Invoke和BeginInvoke是相对于支线线程
近日,被Control的Invoke和BeginInvoke搞的头大,就查了些相关的资料,整理如下. Control的Invoke和BeginInvoke 是相对于支线线程(因为一般在支线线程中调用, ...
- C#中的WinForm的消息机制简述,及消息机制下Invoke,和BeginInvoke的使用和区别
在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate,至于委托的本质请参考我的另一随笔:对.net事件的看法. 一.为什么Control类提供了Invoke和Begin ...
随机推荐
- 关于MAC下的QQ聊天中看不到对方所发的图片解决
使用QQ聊天我们会经常碰到一件让人烦心的事情,那就是别人发的截图自己看不大,是一张裂图(腾讯默认的那张图片).通常有几种情况可以造成这种结果: 第一种原因,网络延迟原因,你的网络不好或者对方的网络不好 ...
- Codeforces Round #368 (Div. 2) A. Brain's Photos (水题)
Brain's Photos 题目链接: http://codeforces.com/contest/707/problem/A Description Small, but very brave, ...
- JAVA应用apache httpclient探测http服务
代码很简单,apache都已经提供了封装. import org.apache.commons.httpclient.HttpClient; import org.apache.commons.htt ...
- IP地址转换成Long型数字的算法
在应用程序开发中,涉及到IP地址的存储,大部分开发人员都将其存为String(或文本类型).能否将固定格式为m.n.x.y的IP地址转换成 Long型的数字呢?答案是肯定的.在数据库层面,可以直接将结 ...
- thinkphp 定位查询 Model:last您所请求的方法不存在!
thinkphp 定位查询 Model:last您所请求的方法不存在! 用thinkphp3.1做项目的时候为了获取记录表中最后一个id用到了last()方法,出现了这个错误:Model:last ...
- 如何在tomcat安装部署php项目
java开发者都知道,tomcat是用来部署java web项目的.前几天老k偶然得知PHP/Java Bridge,通过它可以实现在jsp和php之间共享session,详见<如何实现jsp和 ...
- Using Eclipse With CloudStack
As part of switching to Apache Maven for building CloudStack, the .classpath and .project files used ...
- Android LIstView初次创建getview方法执行多次问题
写listview优化的时候,发现Listview初次创建的时候会多次执行getView方法. <?xml version="1.0" encoding="utf- ...
- GIT 中提示 please tell me who you are
如果使用git过程中出现了,please tell me who you are ,需要设置一下使用者的身份. 1.git config user.name "username" ...
- HttpRuntime.Cache 失效
最近做一个报纸内容类网站,为了提高响应速度,将首页各栏目以及二级栏目中Part文献列表存储在HttpRuntime.Cache缓存中,发布后发现问题,刚插入的缓存很快就失效,本机调试没有问题. 由于H ...