wpf同步与异步执行技术

wpf同步与异步执行技术
wpf同步与异步执行技术

Wpf的同步与异步执行技术

在WPF, 创建的线程DispatcherObject才能访问该对象。例如,从主UI 线程派生的后台线程不能更新的内容Button UI 线程上创建。为了使后台线程访问的内容属性的Button, ,后台线程必须将工作委托给Dispatcher与UI 线程关联。这通过使用实现Invoke 或BeginInvoke。 Invoke 是同步

和BeginInvoke是异步的。该操作将添加到事件队列的Dispatcher指定DispatcherPriority。

1、同步

Invoke 是同步操作;因此,控件不会返回对调用对象直到回调返回后。

同步执行

this.Dispatcher.Invoke(new Action(() => {

//Do Something

//更新UI操作

}));

例如:

如果是窗体本身可使用类似如下的代码:

那么假如是在一个公共类中弹出一个窗口、播放声音等呢?这里我们可以使用:System.Windows.Application.Current.Dispatcher,如下所示

2、异步执行

案例:Wpf 执行异步操作时显示Gif动画。

1)在按钮方法中创建并执行线程:

2)定义异步操作

3)在异步操作中异步修改UI中的控件属性。且该操作中不能执行耗时多的操作,以防UI卡顿。本质是进行两次异步操作。

private void btnRun_Click(object sender, RoutedEventArgs e)

{

startgif.Visibility = Visibility.Visible;

btnClear.IsEnabled = false;

btnRun.IsEnabled = false;

lblShow.Content += "开始系统检查......\n";

//记录操作时间

lblShow.Content += "in btnRun_Click " + DateTime.Now.ToString() + "\n";

//在新线程中异步执行系统检查

Thread newThread = new Thread(GetSystemCheckResult); //创建线程,不带参数

newThread.Start(); //执行线程

//记录操作时间

lblShow.Content += "out btnRun_Click " + DateTime.Now.ToString() + "\n";

}

1. Thread newThread = new Thread(new ParameterizedThreadStart(GetResult)); //可传入参数的线程

2. newThread.Start(inputNumber); //inputNumber为传的参数

1.private void GetResult(object inputNumber) //使用参数inputNumber进行异步操作

2.{

3.double result=CalcSum((Int64)inputNumber);

4.this.Dispatcher.BeginInvoke((Action)delegate()

5. {

6.//this.textBox2.Text = CalcSum((Int64)inputNumber).ToString();

7.this.textBox2.Text = result.ToString();

8. });

9.}

C# 多线程用委托实现异步_调用委托的BeginInvoke和EndInvoke方法

年12月04日15:38:18

?标签:

?异步/

?线程/

?delegate

?5173

1.C#中的每一个委托都内置了BeginInvoke和EndInvoke方法,如果委托的方法列表里只有一个方法,那么这个方法就可以异步执行(不在当前线程里执行,另开辟一个线程执行)。委托的BeginInvoke和EndInvoke方法就是为了上述目的而生的。

2.原始线程发起了一个异步线程,有如下三种执行方式:

方式一:等待一直到完成,即原始线程在发起了异步线程以及做了一些必要处理之后,原始线程就中断并等待异步线程结束再继续执行。

方式二:轮询,即原始线程定期检查发起的线程是否完成,如果没有则可以继续做一些其它事情。

方式三:回调,即原始线程一直执行,无需等待或检查发起的线程是否完成。在发起的线程执行结束,发起的线程就会调用用户定义好的回调方法,由这个回调方法在调用EndInvoke之前处理异步方法执行得到的结果。

3.一个控制台小程序,使用了上面三种方式,执行结果如下:

4.代码:

[csharp]view plain copy

https://www.360docs.net/doc/a14431899.html,ing System;

https://www.360docs.net/doc/a14431899.html,ing System.Collections.Generic;

https://www.360docs.net/doc/a14431899.html,ing System.Linq;

https://www.360docs.net/doc/a14431899.html,ing System.Runtime.Remoting.Messaging;

https://www.360docs.net/doc/a14431899.html,ing System.Text;

https://www.360docs.net/doc/a14431899.html,ing System.Threading;

7.

https://www.360docs.net/doc/a14431899.html,space用委托实现异步_调用BeginInvoke和EndInvoke方法

9.{

10.

11.delegate long MyDel(int first,int second); //声明委托类型

12.

13.class Program

14. {

15.//声明委托类型的方法

16.static long Sum(int x,int y)

17. {

18. Console.WriteLine(" Inside Sum");

19. Thread.Sleep(200);

20.return x + y;

21. }

22.

23.//定义当异步线程执行结束要执行的回调函数

24.static void CallWhenDone(IAsyncResult iar)

25. {

26. Console.WriteLine(" Inside CallWhenDone");

27. AsyncResult ar = (AsyncResult)iar;

28. MyDel del = (MyDel)ar.AsyncDelegate;

29.

30.long result = del.EndInvoke(iar);

31. Console.WriteLine(" The result is {0}.", result);

32. }

33.

34.//方式一:等待异步线程结束,再继续执行主线程

35.static void WaitUntilDoneStyle()

36. {

37. MyDel del = new MyDel(Sum);

38. Console.WriteLine("Before BeginInvoke");

39. IAsyncResult iar = del.BeginInvoke(3, 5, null, null); //开始异步调用

40. Console.WriteLine("After BeginInvoke");

41.

42. Console.WriteLine("Doing main stuff before");

43.long result = del.EndInvoke(iar); //等待异步线程结束并获取结果

44. Console.WriteLine("After EndInvoke:{0}", result);

45. Console.WriteLine("Doing main stuff after");

46. }

47.

48.//方式二:轮询检查异步线程是否结束,若没结束则执行主线程

49.static void LunXunPollingStyle()

50. {

51. MyDel del = new MyDel(Sum);

52. Console.WriteLine("Before BeginInvoke");

53. IAsyncResult iar = del.BeginInvoke(3, 5, null, null); //开始异步调用

54. Console.WriteLine("After BeginInvoke");

55.

56.while (!iar.IsCompleted)

57. {

58. Console.WriteLine("Not Done.Doing main stuff");

59.//继续处理主线程事情

60.for (long i = 0; i < 10000000; i++)

61. ;

62. }

63. Console.WriteLine("Done");

64.long result = del.EndInvoke(iar); //调用EndInvoke来获取结果并进行清理

65. Console.WriteLine("Result: {0}", result);

66. }

67.

68.//方式三:回调方式,当异步线程结束,系统调用用户自定义的方法来处理结果(包括调用委托的EndInvoke方法)

69.static void CallBackStyle()

70. {

71. MyDel del = new MyDel(Sum);

72. Console.WriteLine("Before BeginInvoke");

73. IAsyncResult iar = del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone), null);

74. Console.WriteLine("After BeginInvoke");

75. Console.WriteLine("Doing more work in main.");

76. Thread.Sleep(500);

77. Console.WriteLine("Done with Main. Exiting.");

78. }

79.

80.static void Main(string[] args)

81. {

82.//方式一:等待异步线程结束,再继续执行主线程

83. Console.WriteLine();

84. Console.WriteLine("--------方式一:等待异步线程结束,再继续执行主线程--------");

85. WaitUntilDoneStyle();

86.

87.//方式二:轮询检查异步线程是否结束,若没结束则执行主线程

88. Console.WriteLine();

89. Console.WriteLine("--------方式二:轮询检查异步线程是否结束,若没结束则执行主线程--------");

90. LunXunPollingStyle();

91.

92.//方式三:回调方式,当异步线程结束,系统调用用户自定义的方法来处理结果(包括调用委托的EndInvoke方法)

93. Console.WriteLine();

94. Console.WriteLine("--------方式三:回调方式,当异步线程结束,系统调用用户自定义的方法来处理结果(包括调用委托的EndInvoke方法)----

----");

95. CallBackStyle();

96. }

97.

98.

99. } 100.}

Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析

年09月15日18:06:59

?标签:

?thread/

?c#/

?c#4.0/

?异步/

?delegate

?17372

前段时间,公司同事开发了一个小工具,在工具执行过程中,UI界面一直处于卡死状态。

通过阅读代码发现,主要是由于Dispatcher.BeginInvoke()方法使用不当导致的。

本文将通过一个WPF模拟程序来演示一下界面卡死的现象,并通过修改代码来解决界面卡死的问题。

希望通过对本文的学习,大家能对Dispatcher.BeginInvoke()方法有一个新的认识。

文章开篇直接给出界面卡死的示例代码。

示例WPF程序,用来计算1~n的和值,这里的n可以是1亿~25 亿之间的某个值,通过界面录入,结果显示在n输入框后面的文本框中,既然是WPF程序,代码包含xaml及cs代码两部分,本文一并给出。

以下为cs代码:

[csharp]view plain copy

https://www.360docs.net/doc/a14431899.html,ing System;

https://www.360docs.net/doc/a14431899.html,ing System.Windows;

https://www.360docs.net/doc/a14431899.html,ing System.Threading;

4.

https://www.360docs.net/doc/a14431899.html,space DispatcherExample

6.{

7.///

8./// MainWindow.xaml 的交互逻辑

9.///

10.public partial class MainWindow : Window

11. {

12.public MainWindow()

13. {

14. InitializeComponent();

15. }

16.

17.private void button1_Click(object sender, RoutedEventArgs e)

18. {

19. Int64 inputNumber;

20.if (!Int64.TryParse(this.textBox1.Text, out inputNumber))

21. {

22. MessageBox.Show("请输入1亿-10亿皑间的整型数据!");

23.return;

24. }

25.if (inputNumber > 2500000000 || inputNumber<100000000)

26. {

27. MessageBox.Show("请输入1亿-10亿间的整型数据!");

28.return;

29. }

30. Thread newThread = new Thread(new ParameterizedThreadStart(GetResult));

31. newThread.Start(inputNumber);

32. }

33.

34.private void GetResult(object inputNumber)

35. {

36.this.Dispatcher.BeginInvoke((Action)delegate()

37. {

38.this.textBox2.Text = CalcSum((Int64)inputNumber).ToString();

39. });

40. }

41.

42.private double CalcSum(Int64 inputNumber)

43. {

44.double sum=0;

45.for (int i = 0; i < inputNumber; i++)

46. {

47. sum +=i;

48. }

49.return sum;

50. }

51. }

52.}

以下为xaml代码:

[html]view plain copy

1.

2.xmlns="https://www.360docs.net/doc/a14431899.html,/winfx/2006/xaml/presentation"

3.xmlns:x="https://www.360docs.net/doc/a14431899.html,/winfx/2006/xaml"

4.Title="求(和)你亿万次~~"Height="350"Width="525"ResizeMode="NoResize">

5.

6.

7.

8.

9.

10.

相关文档
最新文档