[同步]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的更多相关文章

  1. .Net基础——程序集与CIL HttpClient封装方法 .Net Core 编码规范 C#中invoke和beginInvoke的使用 WebServeice 动态代理类

    .Net基础——程序集与CIL   1. 程序集和CIL: 程序集是由.NET语言的编译器接受源代码文件产生的输出文件,通常分为 exe和dll两类,其中exe包含Main入口方法可以双击执行,dll ...

  2. C#中Invoke 和 BeginInvoke 的区别

    Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托. Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句 ...

  3. C#中Invoke和BeginInvoke的区别

    1.Invoke() 调用时,Invoke会阻止当前主线程的运行,等到 Invoke() 方法返回才继续执行后面的代码,表现出“同步”的概念. 2.BeginInvoke() 调用时,当前线程会启用线 ...

  4. WPF Invoke和BeginInvoke

    在WPF中Invoke和BeginInvoke和Winform中的是差不多的,只是一个用Control的一个用Dispatcher的. 而Invoke和BeginInvoke的区别嘛 就是一个是同步的 ...

  5. [转载]Winform中Control的Invoke与BeginInvoke方法

    转自http://www.cppblog.com/baby-fly/archive/2010/04/01/111245.html 一.为什么 Control类提供了 Invoke和 BeginInvo ...

  6. C#中的Invoke和BeginInvoke

    一.Control#Invoke() 和Control#BeginInvoke() 在非UI线程中调用MessageBox.Show()结果是非模态对话框: 在UI线程中调用MessageBox.Sh ...

  7. 【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)

    [分析]浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang) 今天无意中看到有关Invoke和BeginInvoke的一些资料,不太清楚它们之间 ...

  8. C#中Control的Invoke和BeginInvoke是相对于支线线程

    近日,被Control的Invoke和BeginInvoke搞的头大,就查了些相关的资料,整理如下. Control的Invoke和BeginInvoke 是相对于支线线程(因为一般在支线线程中调用, ...

  9. C#中的WinForm的消息机制简述,及消息机制下Invoke,和BeginInvoke的使用和区别

    在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate,至于委托的本质请参考我的另一随笔:对.net事件的看法. 一.为什么Control类提供了Invoke和Begin ...

随机推荐

  1. 著名加密库收集 Encrypt

    CryptoAPI 微软的CryptoAPI crypt32.lib,advapi32.lib,cryptui.lib #include <wincrypt.h>#include < ...

  2. 在IT网站上少花些时间

    我自己关注的IT网站还是蛮多的,经常去的有CSDN,博客园,51CTO,InfoQ,还有微博,微信上关注了IT程序猿,IT技术博客大学习,程序员之家, 开发者头条,还有还有,我还通过邮件订阅了码家周刊 ...

  3. Working with Other Node Types

    [Working with Other Node Types] [Shape Nodes Draw Path-Based Shapes] The SKShapeNode class draws a s ...

  4. ucos创建任务的一般方法

    一般说来,任务可在OSStart()启动任务调度之前来创建,也可在任务中创建,但是UC/OS有个规定:在调用OSStart()启动任务调度之前,必须创建了至少一个任务.因此一般习惯上,在OSStart ...

  5. 全球各大运营商黑莓ROM官网下载链接汇总

    全球各大运营商黑莓ROM官网下载链接汇总: 先来关于8830的. 4.2.2.196的rom  8830EFS_PBr4.2.2_rel365_PL3.0.0.85_A4.2.2.196_Sprint ...

  6. Codeforces 706 C. Hard problem (dp)

    题目链接:http://codeforces.com/problemset/problem/706/C 给你n个字符串,可以反转任意一个字符串,反转每个字符串都有其对应的花费ci. 经过操作后是否能满 ...

  7. HDU2553N皇后问题(状态压缩)

    这道题其实最简单的方法就是打表,直接DFS会超时,那就先运行一遍,找出1~10的值,打表即可,这里提供DFS和打表的数据 DFS:(白书上的)TLE #include <stdio.h> ...

  8. 关于dll的路径问题

    最近在做一个sdk二次开发的项目,具体是将一个C++开发的SDk用C#将它的API接口全部封装一遍,然后再做一个demo就好了 好不容易封装完了,在使用的时候出了问题.原来SDK中的dll老是加载不到 ...

  9. CSS学习篇核心之——盒子模型

    概述 关于CSS的一些基础知识我们在前面文章中已经有所了解,这篇文章我们主要来学习下CSS中的核心知识盒子模型的知识. 盒子模型 元素框的最内部分是实际的内容(element),直接包围内容的是内边距 ...

  10. C# 支付宝接口

    生成URL链接   1using System;  2using System.Data;  3using System.Configuration;  4using System.Collectio ...