再谈下 Silverlight 跨线程
新建SL4 应用程序,在MainPage下添加代码:
<Button x:Name="btnThread1" Click="btnThread1_Click">Thread1</Button>
后台代码为:
private void btnThread1_Click(object sender, RoutedEventArgs e) { new Thread(() => { MessageBox.Show("Hello World"); }).Start(); }
如果你运行程序,点击按钮,会得到下面的异常。
这个问题的原因很简单:一个线程尝试调用另一个线程的方法 解决这个异常的方式很简单,
1:使用DependencyObject.Dispatcher.BeginInvoke 方法:
private void btnThread1_Click(object sender, RoutedEventArgs e) { new Thread(() => { this.Dispatcher.BeginInvoke(() => { MessageBox.Show("Hello World"); }); }).Start(); }
2:使用SynchronizationContext 对象
private void btnThread1_Click(object sender, RoutedEventArgs e) { SynchronizationContext context = SynchronizationContext.Current; new Thread(() => { context.Post((state) => { MessageBox.Show("Hello World"); }, null); }).Start(); }
但是这两者都有一个缺陷,假设有多个线程,例如多线程的多线程:
private void btnThread1_Click(object sender, RoutedEventArgs e) { new Thread(() => { SynchronizationContext context = SynchronizationContext.Current; new Thread(() => { context.Post((state) => { MessageBox.Show("Hello World"); }, null); }).Start(); }).Start(); }
虽然这里保存了context,但是因为context并不是UI线程的SynchronizationContext,所以还是会跑出异常。
所以提出了第三种方案:
1:新建静态类UISynchronizationContext,代码如下:
/// <summary> /// UI线程的SynchronizationContext /// </summary> public static class UISynchronizationContext { public static SynchronizationContext Context { get; set; } }
修改App.Xaml.cs 代码的构造函数,在构造App的时候设置
UISynchronizationContext.Context = SynchronizationContext.Current; public App() { this.Startup += this.Application_Startup; this.Exit += this.Application_Exit; this.UnhandledException += this.Application_UnhandledException; //保存UI线程同步上小文 UISynchronizationContext.Context = SynchronizationContext.Current; InitializeComponent(); }
使用的时候只需要:
private void btnThread1_Click(object sender, RoutedEventArgs e) { new Thread(() => { new Thread(() => { UISynchronizationContext.Context.Post((state) => { MessageBox.Show("Hello World"); }, null); }).Start(); }).Start(); }
其实Silverlight 已经提供了相似功能的类了,它就是
System.Windows.Deployment
你完全可以将上面的代码修改为:
new Thread(() => { new Thread(() => { //UISynchronizationContext.Context.Post((state) => // { // MessageBox.Show("Hello World"); // }, null); System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => { MessageBox.Show("Hello World"); }); }).Start(); }).Start();
作者:LoveJenny
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
分类:
C#
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架