其他分享
首页 > 其他分享> > WPF_21_多线程

WPF_21_多线程

作者:互联网

多线程编程可使WPF应用程序执行后台工作,同时保持用户界面能够进行响应。
WPF支持单线程单元(Single-Thread Apartment)模型:

Dispatcher

调度程序(dispatcher)拥有应用程序线程,并管理工作项队列。当程序运行时,调度程序接受新的工作请求,并且一次执行一个任务。

从技术上看,当在新线程中第一次实例化 DispatcherObject类的派生类时,会创建调度程序。如果创建线程相互独立,并用它们显示独立的窗口,最终将创建多个调度程序。不过,大部分都保持简单方式,坚持使用一个用户界面线程和一个调度程序。

DispatcherObject

DispatcherObject实例是绑定到调度程序线程的对象,提供了三个成员:

名称 说明
Dispatcher 返回管理该对象的调度程序
CheckAccess() 如果代码在正确的线程上使用对象,返回true
VerifyAccess() 如果代码在正确的线程上使用对象,就什么都不做,否则抛出 InvalidOperationException 异常

WPF对象为保护自身会频繁调用 VerifyAccess() 方法,从而不可能在错误的线程中长时间使用一个对象。

BackgroundWorker

有很多方法执行异步操作,比如创建 Thread 对象。可以创建几十个线程,但如果访问共享数据就需要使用锁定机制来避免潜在错误。另外频繁创建线程或大量创建线程会产生额外的,不必要的开销。

BackgroundWorker用于简化 Windows 窗体应用程序中与线程相关的问题。为单独线程中运行耗时的任务提供了简单的方法,它在后台使用调度程序,并使用基于事件的模型对封送问题进行抽象。可以使用两个方法创建实例:

<Window.Resources>
    <cm:BackgroundWorker x:Key="backgroundWorker"
        WorkerReportsProgress="True" WorkerSupportsCancellation="True"
        DoWork="backgroundWorker_DoWork"
        ProgressChanged="backgroundWorker_ProgressChanged"
        RunWorkerCompleted="backgroundWorker_RunWorkerCompleted"/>
</Window.Resources>
  1. 调用 RunWorkerAsynce() 方法时,可提供一个对象,然后会被传递到 DoWork 事件中。
  2. 当开始执行后,从CLR线程池提取一个自由线程,然后从这个线程引发DoWork事件.此时不能访问共享数据或用户界面
  3. 完成耗时工作就会引发 RunWorkerCompleted事件通知应用程序。这个事件在调度程序线程引发,此时可以访问共享数据和用户界面

跟踪进度

如果要实现 跟踪进度 ,首先DoWork事件处理代码需要调用 ReportProgress() 方法,并提供已经完成的百分比。每次调用 ReportProgress() 方法时,都会引发 ProgressChanged 事件,此事件是从用户界面线程引发的,所以不需要使用 Dispatcher.BeginInvoke()方法。

private void UpdateProgress()
{
    backgroundWorker.ReportProgress(p);
}

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // 此事件在UI线程
    progressBar.Value = e.ProgressPercentage;
}

支持取消

为请求取消,代码需要调用 CancelAsync() 方法。此时不会自动发生任何操作,相反执行任务的代码(DoWork方法)需要显示地检查取消请求,执行所有清除操作,然后返回。

private void cmdCancel_Click(object sender, RoutedEventArgs e)
{
    // 手动触发取消
    backgroundWorker.CancelAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkerEventArgs e)
{
    // 省略代码
    if (backgroundWorker.CancellationPending)
    {
        e.Cancel = true;
        return;
    }
    // 省略代码

    e.Result = result;
}

当取消操作时,仍会引发 RunWorkerCompleted 事件,此时可检查任务是否已经被取消并进行相应处理。

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if(e.Cancelled)
    {
        MessageBox.Show("Search cancelled.");
    }
    else if(e.Error != null)
    {
        MessageBox.Show(e.Error.Message, "An Error Occurred");
    }
    else
    {
        // 正常结束耗时任务
    }

    progressBar.Value = 0;
}

我的公众号 HelloProgram

标签:21,对象,代码,调度,backgroundWorker,线程,WPF,多线程
来源: https://www.cnblogs.com/jqwang/p/15878576.html