在 WPF 中的线程

线程处理使程序能够执行并发处理,以便它可以做多个操作一次。节省开发人员从线程处理困难的方式,设计了 WPF (窗口演示文稿基金会)。这篇文章可以帮助理解线程在 WPF 中的正确用法。

WPF 内部线程和规则

所有 WPF 应用程序中都运行两个线程:

  1. 为呈现-它在后台运行,所以,它被隐藏。
  2. 用于管理 UI 界面 (UI 线程) — —

大多数 WPF 对象与 UI 线程被束缚。它接收输入、 绘制屏幕、 运行的代码和处理事件。

WPF 支持单线程单元模型,有以下规则:

  1. 一个线程在整个应用程序中运行,并拥有所有 WPF 对象。
  2. WPF 元素有其他线程不能彼此交互的线程亲和手段。
  3. 具有线程关联的 WPF 对象从调度程序对象派生。

线程处理在 WPF 中由开发商

而在 WPF 开发人员都需要如此管理线程在某些情况下创建应用程序,它提供了一些方法来处理,并在不同的场景上的应用程序中使用的线程。以下是为处理线程的两种方式:

  1. 调度程序
  2. 后台辅助线程。

调度程序

调度程序是System.Windows.Threading 的一个实例。调度员类。它拥有应用程序线程和管理队列的工作项。它的每个优先,以执行 UI 操作以 fifo (先进先出) 的方式。它并不创建新的线程。它不是多线程的。

每个视觉 WPF 对象从DispatcherObject派生。它是一个链接到 DispatcherObject 类的对象。以下是 DispatcherObject 类的成员:

(1) 属性

  1. 调度员: 它获取调度程序。

(2) 方法:

在 DispatcherObject Class 中有几种方法。一些重要的方法如下:

  1. Checkaccess 方法 (): 它返回 true,则代码是一个正确的线程使用的对象。
  2. VerifyAccess (): 如果是没有的代码是在使用对象否则为会引发与"能反转"正确的线程上。
  3. 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 的执行。以下是某些情况下可以使用后台辅助线程的场合:

  1. 如果用户想要在特定的操作响应 UI 和面孔延误。
  2. 数据下载。
  3. 数据库事务。

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%

..........................

调度程序和后台辅助线程之间的区别:

  1. 后台辅助线程执行的代码在同一时间在一个单独的线程中调用它。调度程序处理的事情要做每一次队列时,它可自动同步和 WPF 应用程序的主线程。
  2. 后台辅助线程在单独的线程中执行与 WPF 应用程序的 UI 线程调度程序运行的同时。
  3. 如果你想要在后台运行操作,向用户界面,使用一个后台工作人员但使用调度程序封送回对 WPF UI 的更新。
时间: 2024-10-11 04:17:30

在 WPF 中的线程的相关文章

线程在WPF中的使用

项目中可能会有这样的需求,一直获取新的某个数据信息,但仍不影响其他的操作功能,这时就用到了线程,获取新数据放到线程中操作,对其他操作不产生影响,下面就以随机获取数组中项为例解说WPF中使用线程这一实例:在WPF窗体程序中拖三个Button 两个操作按钮,一个启动按钮.后台代码: public delegate void GetSetNumber();// bool IsContinue = true; public ThreadModel() { InitializeComponent(); }

WPF中窗口控件的跨线程调用

原文:WPF中窗口控件的跨线程调用 在WinForm中,我们要跨线程访问窗口控件,只需要设置属性CheckForIllegalCrossThreadCalls = false;即可. 在WPF中要麻烦一下,同样的不允许跨线程访问,因为没有权限,访问了会抛异常: 没有CheckForIllegalCrossThreadCalls 属性,怎么办? 在WPF中的窗口控件都有一个Dispatcher属性,允许访问控件的线程:既然不允许直接访问,就告诉控件我们要干什么就好了. 方法如下: private

将 C++/WinRT 中的线程切换体验带到 C# 中来(WPF 版本)

原文:将 C++/WinRT 中的线程切换体验带到 C# 中来(WPF 版本) 如果你要在 WPF 程序中使用线程池完成一个特殊的任务,那么使用 .NET 的 API Task.Run 并传入一个 Lambda 表达式可以完成.不过,使用 Lambda 表达式会带来变量捕获的一些问题,比如说你需要区分一个变量作用于是在 Lambda 表达式中,还是当前上下文全局(被 Lambda 表达式捕获到的变量).然后,在静态分析的时候,也难以知道此 Lambda 表达式在整个方法中的执行先后顺序,不利于分

WPF中嵌入普通Win32程序的方法

公司现在在研发基于.Net中WPF技术的产品,由于要兼容旧有产品,比如一些旧有的Win32程序.第三方的Win32程序等等,还要实现自动登录这些外部Win32程序,因此必须能够将这些程序整合到我们的系统中来,让使用者看起来它们好像是一个程序. 在MSDN中有专门的章节提到了在WPF中嵌入Win32控件的办法,那就是使用 HwndHost ,只要把 Win32控件的句柄传递给 HwndHost 就可以了.MSDN中的例子演示的都是在同一个进程内创建的 Win32控件,我一开始认为只要通过FindW

WPF中的动画——(一)基本概念

WPF的一个特点就是支持动画,我们可以非常容易的实现漂亮大方的界面.首先,我们来复习一下动画的基本概念.计算机中的动画一般是定格动画,也称之为逐帧动画,它通过每帧不同的图像连续播放,从而欺骗眼和脑产生动画效果.其原理在维基百科上有比较详尽的解释,这里就不多介绍了. 也就是说,我们要产生动画,只需要连续刷新界面即可.例如,我们要实现一个宽度变化的按钮的动画,可以用如下方式来实现: private void MainWindow_Loaded(object sender, RoutedEventAr

WPF中异步更新UI元素

XAML 界面很简单,只有一个按钮和一个lable元素,要实现点击button时,lable的内容从0开始自动递增. <Grid> <Label Name="lable_plus" Content="0"/> <Button Content="Button" Click="button_Click" Height="23" Name="button" Wid

WinForm与WPF下跨线程调用控件

Winform下: public delegate void UpadataTextCallBack(string str,TextBox text); public void UpadtaText(string str, TextBox text) { if (text.InvokeRequired) { UpadataTextCallBack upadataTextCallBack = UpadtaText; text.Invoke(upadataTextCallBack, new obje

WPF中的多线程(一)

首先我们先来看一个例子,用来计算一定范围内的素数个数. XAML: <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto&quo

WPF中多线程统计拆箱装箱和泛型的执行效率

WPF中多线程统计拆箱装箱和泛型的执行效率,使用的知识点有泛型.多线程.委托,从例子中可以看到使用泛型的效率至少提升2倍 MainWindow.xaml <Window x:Class="Box.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xa