线程处理使程序能够执行并发处理,以便它可以做多个操作一次。节省开发人员从线程处理困难的方式,设计了 WPF (窗口演示文稿基金会)。这篇文章可以帮助理解线程在 WPF 中的正确用法。
WPF 内部线程和规则
所有 WPF 应用程序中都运行两个线程:
- 为呈现-它在后台运行,所以,它被隐藏。
- 用于管理 UI 界面 (UI 线程) — —
大多数 WPF 对象与 UI 线程被束缚。它接收输入、 绘制屏幕、 运行的代码和处理事件。
WPF 支持单线程单元模型,有以下规则:
- 一个线程在整个应用程序中运行,并拥有所有 WPF 对象。
- WPF 元素有其他线程不能彼此交互的线程亲和手段。
- 具有线程关联的 WPF 对象从调度程序对象派生。
线程处理在 WPF 中由开发商
而在 WPF 开发人员都需要如此管理线程在某些情况下创建应用程序,它提供了一些方法来处理,并在不同的场景上的应用程序中使用的线程。以下是为处理线程的两种方式:
- 调度程序
- 后台辅助线程。
调度程序
调度程序是System.Windows.Threading 的一个实例。调度员类。它拥有应用程序线程和管理队列的工作项。它的每个优先,以执行 UI 操作以 fifo (先进先出) 的方式。它并不创建新的线程。它不是多线程的。
每个视觉 WPF 对象从DispatcherObject派生。它是一个链接到 DispatcherObject 类的对象。以下是 DispatcherObject 类的成员:
(1) 属性
- 调度员: 它获取调度程序。
(2) 方法:
在 DispatcherObject Class 中有几种方法。一些重要的方法如下:
- Checkaccess 方法 (): 它返回 true,则代码是一个正确的线程使用的对象。
- VerifyAccess (): 如果是没有的代码是在使用对象否则为会引发与"能反转"正确的线程上。
- GetType (): 它获取当前实例的类型。
WPF 对象调用VerifyAccess () 频繁地项目本身。
我们为什么需要调度程序?
将澄清的调度员在 WPF 应用程序中需要一个例子:
1 using System; 2 using System.Threading; 3 using System.Windows; 4 5 namespace WpfApplication1 6 { 7 /// <summary> 8 /// Interaction logic for WPF UI Upadation using 9 /// thread. 10 /// </summary> 11 12 public partial class MainWindow : Window 13 { 14 15 public MainWindow() 16 { 17 InitializeComponent(); 18 } 19 20 private void MyButton_Click(object sender, RoutedEventArgs e) 21 { 22 Thread thread = new Thread(UpdateText); 23 thread.Start(); 24 } 25 26 private void UpdateText() 27 { 28 Thread.Sleep(TimeSpan.FromSeconds(5)); 29 TxtName.Text = "Hello Geeks !"; 30 } 31 } 32 }
现在,这是一个错误的代码,因为将会在一个新线程,执行UpdateText()的方法,不允许线程访问 WPF 对象。
"VerifyAccess()"方法调用和不能被"加载"。
以上代码的校正:
1 using System; 2 using System.Threading; 3 using System.Windows; 4 5 namespace WpfApplication1 6 { 7 /// <summary> 8 /// Interaction logic for WPF UI Upadation using 9 /// Dispatcher. 10 /// </summary> 11 12 public partial class MainWindow : Window 13 { 14 public MainWindow() 15 { 16 17 InitializeComponent(); 18 } 19 20 private void MyButton_Click(object sender, RoutedEventArgs e) 21 { 22 23 Thread thread = new Thread(UpdateText); 24 thread.Start(); 25 } 26 27 private void UpdateText() 28 { 29 Thread.Sleep(TimeSpan.FromSeconds(5)); 30 this.Dispatcher.BeginInvoke(new Action(() => 31 { 32 TxtName.Text = "Hello Geeks !"; 33 })); 34 } 35 } 36 }
所以,调度程序是与线程更新 WPF 用户界面的最佳途径。
后台辅助线程
它是非常有利的耗时的任务。它在同一时间执行的代码。它是在一个单独的线程中调用。它会自动与应用程序的主线程进行同步。
它用来在后台运行操作和延迟到 UI 的执行。以下是某些情况下可以使用后台辅助线程的场合:
- 如果用户想要在特定的操作响应 UI 和面孔延误。
- 数据下载。
- 数据库事务。
BackgroundWorker 是在System.ComponentModel下的类。它将执行一个单独的线程上运行。
1 using System; 2 using System.ComponentModel; 3 using System.Threading; 4 5 namespace BackGroundWorkerExample 6 { 7 8 /// <summary> 9 /// It implements backgroundworker. 10 /// </summary> 11 12 class Program 13 { 14 15 private static BackgroundWorker backgroundWorker; 16 static void Main(string[] args) 17 { 18 backgroundWorker = new BackgroundWorker 19 { 20 WorkerReportsProgress = true, 21 WorkerSupportsCancellation = true 22 }; 23 24 //Event creation. 25 26 //For the performing operation in the background. 27 28 backgroundWorker.DoWork += backgroundWorker_DoWork; 29 30 //For the display of operation progress to UI. 31 32 backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged; 33 34 //After the completation of operation. 35 36 backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted; 37 38 backgroundWorker.RunWorkerAsync("Press Enter in the next 5 seconds to Cancel operation:"); 39 40 Console.ReadLine(); 41 42 if (backgroundWorker.IsBusy) 43 { 44 backgroundWorker.CancelAsync(); 45 Console.ReadLine(); 46 } 47 }
现在,在背景中执行操作。
1 /// <summary> 2 /// Performs operation in the background. 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 7 static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 8 { 9 10 for (int i = 0; i < 200; i++) 11 { 12 if (backgroundWorker.CancellationPending) 13 { 14 e.Cancel = true; 15 return; 16 } 17 18 backgroundWorker.ReportProgress(i); 19 Thread.Sleep(1000); 20 e.Result = 1000; 21 } 22 }
为执行操作进度的更改事件。
1 /// <summary> 2 /// Displays Progress changes to UI . 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 7 static void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 8 { 9 Console.WriteLine("Completed" + e.ProgressPercentage + "%"); 10 }
通过使用 Runworker 完成事件显示结果:
1 /// <summary> 2 /// Displays result of background performing operation. 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 7 static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 8 { 9 if (e.Cancelled) 10 { 11 Console.WriteLine("Operation Cancelled"); 12 } 13 else if (e.Error != null) 14 { 15 Console.WriteLine("Error in Process :" + e.Error); 16 } 17 else 18 { 19 Console.WriteLine("Operation Completed :" + e.Result); 20 } 21 22 }
输出:
已完成的 0%
已完成的 1%
已完成的 2%
..........................
调度程序和后台辅助线程之间的区别:
- 后台辅助线程执行的代码在同一时间在一个单独的线程中调用它。调度程序处理的事情要做每一次队列时,它可自动同步和 WPF 应用程序的主线程。
- 后台辅助线程在单独的线程中执行与 WPF 应用程序的 UI 线程调度程序运行的同时。
- 如果你想要在后台运行操作,向用户界面,使用一个后台工作人员但使用调度程序封送回对 WPF UI 的更新。