您好,欢迎来到抵帆知识网。
搜索
您的当前位置:首页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操作 }));

例如:

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

1 2 3 4 this.lblState.Dispatcher.Invoke(new Action(delegate { this.lblState.Content = \"状态:\" + this._statusText; }));

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

1 System.Windows.Application.Current.Dispatcher.Invoke(new Action(() => 2 { 3 if (path.EndsWith(\".mp3\") || path.EndsWith(\".wma\") || path.EndsWith(\".wav\")) 4 { 5 _player.Open(new Uri(path)); 6 _player.Play(); 7 } 8 }));

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((Int)inputNumber); 4. this.Dispatcher.BeginInvoke((Action)delegate() 5. {

6. //this.textBox2.Text = CalcSum((Int)inputNumber).ToString(); 7. this.textBox2.Text = result.ToString(); 8. }); 9. }

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

原创 2014年12月04日 15:38:18

    

标签: 异步 / 线程 / delegate 5173

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

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

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

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

方式三:回调,即原始线程一直执行,无需等待或检查发起的线程是否完成。在发起的线程执行结束,发起的线程就会调用用户定义好的回调方法,由这个回调方法在调用EndInvoke之前处理异步方法执行得到的结果。 3.一个控制台小程序,使用了上面三种方式,执行结果如下:

4.代码:

[csharp] view plain copy

1. using System;

2. using System.Collections.Generic; 3. using System.Linq;

4. using System.Runtime.Remoting.Messaging; 5. using System.Text; 6. using System.Threading; 7.

8. namespace 用委托实现异步_调用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); //开始异步调用 . 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\");

. 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();

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

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

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

95. CallBackStyle(); 96. } 97. 98.

99. } 100. }

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

原创 2013年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

1. using System;

2. using System.Windows; 3. using System.Threading; 4.

5. namespace 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. Int inputNumber;

20. if (!Int.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((Int)inputNumber).ToString(); 39. }); 40. } 41.

42. private double CalcSum(Int 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=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" 3. xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"

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

6.

7. 8. 9.

10.

Copyright © 2019- dfix.cn 版权所有 湘ICP备2024080961号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务