写 WPF 的童鞋可能都会碰到 在非UI线程中访问 UI 异常的问题。这是为了防止数据不一致做的安全限制。

子线程中更新UI还要交给主线程更新,引用满天飞,实在是麻烦。

接下来,我们推出一个可以称之为框架的解决方案(拍砖的时候轻点)。

一:解决判断当前线程是主线成的问题

在 C# 中 微软好像没有给出直接判断当前线程是否是主线程的方案,至少我是没找到。

如果您有更好的解决方案请留言哦!!!!

/// <summary>
/// Lyx 线程框架 类
/// </summary>
public class LyxThreadFrame
{
/// <summary>
/// 主线程 签名
/// </summary>
public const string MainThreadIdiograph = "Main Thread"; /// <summary>
/// 初始化 线程检测框架
/// <para>请在UI(主)线程下初始化</para>
/// </summary>
public static void Init()
{
var thread = System.Threading.Thread.CurrentThread;
thread.Name = MainThreadIdiograph;
}
}

我的解决方案是,在程序启动的时候先给主线程命名

public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
LyxThreadFrame.Init();
base.OnStartup(e);
}
}

我会重写 Application 类的 OnStartup() 方法,在这个方法中去初始化当前框架

OnStartup() WPF 程序启动的入口点,主窗口的创建就是在这里了。

/// <summary>
/// 线程 扩展类
/// </summary>
public static class ThreadExtension
{
/// <summary>
/// 当前线程是否是主线程
/// </summary>
public static bool IsMainThread(this Thread thread)
{
if (thread == null)
{
throw new ArgumentNullException("thread");
}
if (thread.Name == null)
{
return false;
}
return thread.Name.Equals(LyxThreadFrame.MainThreadIdiograph);
}
}

扩展线程类,用于判断当前方法是否是主线程,判断下指定线程是否是哥当初赏赐了名字的那个线程。

好了,到这里就能判断当前线程是否是主线程了。

二:让你的UI 访问代码在UI(主)线程下执行

/// <summary>
/// 委托 扩展类
/// </summary>
public static class DelegateExtension
{
/// <summary>
/// 在UI(主)线程中执行
/// </summary>
public static object SafetyInvoke(this Delegate dele, params object[] param)
{
var thread = System.Threading.Thread.CurrentThread;
if (thread.IsMainThread())
{
return dele.DynamicInvoke(param);
}
else
{
return Application.Current.Dispatcher.Invoke(dele, param);
}
}
}

在这里我们扩展了 Delegate 这里有个 Application 类,我们程序中的 App 就是继承了这个。它是程序的入口点。

这样我们就创建了一个安全的 访问UI的环境。

示例:

public void Hello()
{
var action = new Action(() =>
{
//更新UI
});
  action.SafetyInvoke();
}

一个解决在非UI线程中访问UI 异常的小方法的更多相关文章

  1. UWP 在非UI线程中更新UI

    大家都知道,不可以在 其他线程访问 UI 线程,访问 UI 线程包括给 依赖属性设置值.读取依赖属性.调用方法(如果方法里面修改了依赖属性)等.一旦访问UI线程,那么就会报错,为了解决这个问题,需要使 ...

  2. Android开之在非UI线程中更新UI

    当在非UI线程中更新UI(程序界面)时会出现例如以下图所看到的的异常: 那怎样才干在非UI线程中更细UI呢? 方法有非常多种.在这里主要介绍三种: 第一种:调用主线程mHandler的post(Run ...

  3. 为什么在非UI线程中操作UI的改变失不安全的

    因为你如果允许在非UI线程更新操作UI的东西,那我再另一个非UI线程也可以更新这个Ui的东西 这样就会有冲突,比如你的线程刚好跑到修改UI这里,我的另一个UI也有可能跑到这里,所以这样导致线程不安全. ...

  4. Android在非UI线程中更新UI的方法

    1.使用Thread+Handler实现非UI线程更新UI界面 在UI Thread中创建Handler.用sendMessage(message)或者obtainMessage(result, ob ...

  5. 在非UI线程中更改UI(Delphi使用隐藏窗口来处理,QT使用信号槽)

    在Delphi里我记得是使用TThread.Synchronize(TThreadMethod),原理是利用了一个隐藏窗口来处理. 在QT Debug模式一下,碰到了同样的问题,显示错误: canno ...

  6. android在其他线程中访问UI线程的方法

    1.Activity.runOnUiThread( Runnable ) 2.View.post( Runnable ) 3.View.postDelayed( Runnable, long ) 4. ...

  7. android4.0以上访问网络不能在主线程中进行以及在线程中操作UI的解决方法

    MONO 调用一个线程操作UI 然后报Only the original thread that created a view hierarchy can touch its views.错误 goo ...

  8. Android 高级UI设计笔记17:Android在非UI线程中显示Toast

    1. 子线程的Toast怎么显示不出来? 因为Toast在创建的时候会依赖于一个Handler,并且一个Handler是需要有一个Looper才能够创建,而普通的线程是不会自动去创建一个Looper对 ...

  9. Android中高效的显示图片之二——在非UI线程中处理图片

    在“加载大图”文章中提到的BitmapFactory.decode*方法,如果源数据是在磁盘.网络或其它任何不是在内存中的位置,那么它都不应该在UI线程中执行.因为它的加载时间不可预测且依赖于一系列因 ...

随机推荐

  1. 不小心把sudoer改错了的补救方法

    原本是感觉每次 sudo command 都要输入密码太费事了,就想把密码去掉.好了怎么去掉呢,自然是修改 /etc/sudoers 可是不小心修改错了,结果悲剧出现了:由于是在非root用户模式下, ...

  2. Android------第一次启动出现白屏或者黑屏

    APP开发中,第一次运行启动app时,会出现一会儿的黑屏或者白屏才进入Activity的界面显示. 当打开一个Activity时,如果这个Activity所属Application还没有在运行, 系统 ...

  3. MyBatis的返回参数类型

    MyBatis的返回参数类型分两种 1. 对应的分类为: 1.1.resultMap: 1.2.resultType: 2 .对应返回值类型: 2.1.resultMap:结果集 2.2.result ...

  4. poj 3411 Paid Roads很水的DFS

    题意:给你N 城市和M条道路,每条道路要付的钱,但是如果你在这个道路上你可以付其他道路的钱(跟走到的时候去的话不一样),问你从1走到N最少话费是多少. 直接DFS搜. 链接http://poj.org ...

  5. SqlServer中存储过程 returnC#代码处理以及对应的MySQL如何改写

    一.SqlServer 中 1. 创建表 create table testuser( id int, --primary key, names ), address ), paw ) ) 2.创建存 ...

  6. Java 进阶6 异常处理的陷阱

    Java 进阶6 异常处理的陷阱 20131113 异常处理机制是 Java语言的特色之一,尤其是 Java的Checked 异常,更是体现了 Java语言的严谨性:没有完善的错误的代码根本就不会被执 ...

  7. 转载:【Oracle 集群】RAC知识图文详细教程(五)--特殊问题和实战经验

    文章导航 集群概念介绍(一) ORACLE集群概念和原理(二) RAC 工作原理和相关组件(三) 缓存融合技术(四) RAC 特殊问题和实战经验(五) ORACLE 11 G版本2 RAC在LINUX ...

  8. Linq的使用 <一>

    一.种类 1.Linq to Objects,实现了IEnumerable<T>集合对象的集成查询 2.Linq to sql,针对关系数据库MSSQL的解释查询 3.Linq to En ...

  9. 关于vue+element-ui的table多选禁用某个按钮

    在我做的项目中,有这样一个需求:当table多选没有勾选数据的时候禁用掉导出按钮 效果如图:      当选择一个时候可以导出这行的数据 在按钮定义  :disabled="selected ...

  10. RabbitMQ(6) 集群部署

    单节点部署 rabbitmq单节点部署比较简单,可以使用apt-get等工具快速安装部署. wget -O- https://www.rabbitmq.com/rabbitmq-release-sig ...