写 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. Eclipse 中从SVN下载的项目如何解除关联上传到另一SVN路径下

    首先选中项目右击-->team-->断开连接  选择第一个即可断开与上一个SVN关联 然后上传到另一SVN路径下 选中项目右击-->team-->Share Project  ...

  2. 第九天 1-8 实战:安装nginx服务器

    简介:使用nginx源码包,安装nginx服务器,并对其进行配置后,测试其成果.模仿百度主页! 第一步:检查依赖关系[root@xiaogan ~]# rpm -q zlib-devel pcre-d ...

  3. 三十二 Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy的暂停与重启

    scrapy的每一个爬虫,暂停时可以记录暂停状态以及爬取了哪些url,重启时可以从暂停状态开始爬取过的URL不在爬取 实现暂停与重启记录状态 1.首先cd进入到scrapy项目里 2.在scrapy项 ...

  4. mongodb安装与权限配置

    mongodb下载地址:官方下载IDE工具:Robo 3T:官方下载 windows系统要求64位,最低2g内存,推荐8g内存及以上 安装过程没有需要配置的地方,直接下一步到结束,如果想要方便可以在环 ...

  5. SSH集成log4j日志环境

    第一步:在web.xml初始化log4j <context-param> <param-name>contextConfigLocation</param-name> ...

  6. garylog学习篇

    官方文档:https://www.graylog.org/ 简介 Graylog 是一个简单易用.功能较全面的日志管理工具,相比 ELK 组合, 优点: 部署维护简单查询语法简单易懂(对比ES的语法… ...

  7. Django WSGI,MVC,MTV,中间件部分,Form初识

    一.什么是WSGI? WEB框架的本质是一个socket服务端接收用户请求,加工数据返回给客户端(Django),但是Django没有自带socket需要使用 别人的 socket配合Django才能 ...

  8. Flask项目中数据库迁移的使用

    数据库迁移 在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库.最直接的方式就是删除旧表,但这样会丢失数据. 更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化,然后把变动应用 ...

  9. 《Drools7.0.0.Final规则引擎教程》Springboot+规则重新加载

    在<Drools7.0.0.Final规则引擎教程>之Springboot集成中介绍了怎样将Drools与Springboot进行集成,本篇博客介绍一下集成之后,如何实现从数据库读取规则并 ...

  10. Java API访问ZK的权限控制

    无权限访问结点 /** * 对于ZK的授权访问 * Created by liuhuichao on 2017/7/27. */ public class AutoSample { private s ...