2018-10-18-WPF-跨线程-UI-的方法
title | author | date | CreateTime | categories |
---|---|---|---|---|
WPF 跨线程 UI 的方法
|
lindexi
|
2018-10-18 10:25:28 +0800
|
2018-10-18 09:24:10 +0800
|
WPF
|
本文告诉大家如何在 WPF 使用多线程的 UI 的方法
在很多的时候都是使用单线程的 UI 但是有时候需要做到一个线程完全处理一个耗时的界面就需要将这个线程作为另一个 UI 线程
在 WPF 可以使用 VisualTarget 做到多个 UI 线程的绘制,注意这里的 WPF 的渲染线程只有一个,多个 UI 线程无法让渲染的速度加快。如果一个界面有很多的 Visual 那么渲染速度也不会因为添加 UI 线程用的时间比原来少
在 WPF 的 VisualTarget 可以用来连接多个不同的线程的 UI 元素,在使用的时候只需要创建,然后在另一个 UI 线程将创建的元素添加到 RootVisual 就可以
var thread = new Thread(() =>
{
_visualTarget = new VisualTarget(xx); _visualTarget.RootVisual = 创建的 Visual;
});
创建一个 VisualTarget 需要用到 HostVisual 通过 HostVisual 可以在多个线程连到视觉树,所以创建 HostVisual 需要在主线程
public MainWindow()
{
InitializeComponent(); var hostVisual = new HostVisual(); var thread = new Thread(() =>
{
_visualTarget = new VisualTarget(hostVisual); _visualTarget.RootVisual = 创建的 Visual;
});
}
这时还需要将 hostVisual 加入视觉树,因为 HostVisual 也是 Visual 最简单将 Visual 加入视觉树的方法是创建一个类继承 UIElement 的方法,请看下面代码
public class DispatcherContainer : UIElement
{
/// <inheritdoc />
protected override Visual GetVisualChild(int index)
{
return _hostVisual;
} /// <inheritdoc />
protected override int VisualChildrenCount => 1; private readonly HostVisual _hostVisual = new HostVisual();
}
然后在构造函数添加一个线程用来创建另一个 UI 线程,创建一个 UI 线程的最简单方法是运行 Dispatcher.Run()
和设置线程 STA 才可以,注意这里的 Dispatcher
是静态类
var thread = new Thread(() =>
{ System.Windows.Threading.Dispatcher.Run();
}); thread.SetApartmentState(ApartmentState.STA);
thread.Start();
在这个线程里添加 VisualTarget 请看下面
var thread = new Thread(() =>
{
_visualTarget = new VisualTarget(_hostVisual); _visualTarget.RootVisual = 创建的元素; System.Windows.Threading.Dispatcher.Run();
}); thread.SetApartmentState(ApartmentState.STA);
thread.Start();
下面创建一个简单的元素在另一个线程
var thread = new Thread(() =>
{
_visualTarget = new VisualTarget(_hostVisual);
DrawingVisual drawingVisual = new DrawingVisual();
var drawing = drawingVisual.RenderOpen();
using (drawing)
{
var text = new FormattedText("欢迎访问我博客 http://lindexi.gitee.io 里面有大量 UWP WPF 博客",
CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
new Typeface(new FontFamily("微软雅黑"), new FontStyle(), FontWeight.FromOpenTypeWeight(1),
FontStretch.FromOpenTypeStretch(1)), 20, Brushes.DarkSlateBlue); drawing.DrawText(text, new Point(100, 100));
} var containerVisual = new ContainerVisual(); containerVisual.Children.Add(drawingVisual); _visualTarget.RootVisual = containerVisual; System.Windows.Threading.Dispatcher.Run();
}); thread.SetApartmentState(ApartmentState.STA);
thread.Start();
这时的 DispatcherContainer 类看起来是这样
public class DispatcherContainer : UIElement
{
/// <inheritdoc />
public DispatcherContainer()
{
var thread = new Thread(() =>
{
_visualTarget = new VisualTarget(_hostVisual);
DrawingVisual drawingVisual = new DrawingVisual();
var drawing = drawingVisual.RenderOpen();
using (drawing)
{
var text = new FormattedText("欢迎访问我博客 http://lindexi.gitee.io 里面有大量 UWP WPF 博客",
CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
new Typeface(new FontFamily("微软雅黑"), new FontStyle(), FontWeight.FromOpenTypeWeight(1),
FontStretch.FromOpenTypeStretch(1)), 20, Brushes.DarkSlateBlue); drawing.DrawText(text, new Point(100, 100));
} var containerVisual = new ContainerVisual(); containerVisual.Children.Add(drawingVisual); _visualTarget.RootVisual = containerVisual; System.Windows.Threading.Dispatcher.Run();
}); thread.SetApartmentState(ApartmentState.STA);
thread.Start();
} /// <inheritdoc />
protected override Visual GetVisualChild(int index)
{
return _hostVisual;
} /// <inheritdoc />
protected override int VisualChildrenCount => 1; private readonly HostVisual _hostVisual = new HostVisual();
private VisualTarget _visualTarget;
}
为了显示元素,需要添加到界面,打开界面添加下面代码
<local:DispatcherContainer></local:DispatcherContainer>
运行可以看到下面界面,这里的文字是在另一个线程绘制,但是也是和主界面在相同的线程渲染
代码请看 https://github.com/lindexi/UWP/tree/master/wpf/CaitrairSodeyatarFowfurur
最新文章
- MailKit---状态更改和删除
- Perst常用命令
- Ubuntu14.04手动创建桌面快捷方式
- hadoop HA 之 QJM
- 学习笔记——XSLT转换器的使用(Xalan和Saxon) .(转)
- Asp.net Gridview导出Excel
- Firefox使用Poster插件发送post请求
- 更改Qt Application为 Qt Console Application
- Java并发框架——AQS阻塞队列管理(三)——CLH锁改造
- pyzmq学习笔记
- POJ 3126 Prime Path【BFS】
- PHP利用get_headers()函数判断远程的url地址是否有效
- Gitblit版本服务器环境部署记录
- ObservableData-另一种姿势的观察者模式
- Fb 第三方接口
- idea 和 WebStorm 配置 http代理 并更换主题
- CentOS7网卡改名
- Kafka server部署配置优化
- js获取下拉,单选
- git学习------>从SVN迁移到Git之后,项目开发代码继续在SVN提交,如何同步迁移之后继续在SVN提交的代码到Git?