写 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. Linux虚拟机忘记root密码的拯救办法

    于是百度之,还是有很多解决方案的.其原理就是,进入到single单用户模式下,去修改root密码: 1.重启系统,选择Linux引导,然后按住e,出现如下界面: 按下e 出现如下页面 选择kernel ...

  2. Android----Material Design之(FloatActionButton,CoordinatorLayout,CollapsingToolbarLayout,AppBarLayout,TabLayout等)

    Material Design 的一些UI 平常开发还是用的比较多的,以前没写,最近总结一下,写一篇博客,要求版本在5.0以上. 主要介绍了FloatActionButton,CoordinatorL ...

  3. MySQL设置某一字段默认为0,但是插入数据化却显示为null

    1.MySQL字段默认的含义:在插入时不指定该字段的值:2.以mybatis举例,如果是插入实体,那么为空的字段就会插入空:3.如果不想mybatis等持久化工具插入空,可以尝试insertSelec ...

  4. Node-Media-Server

    Node-Media-Server (相对稳定可用性高) 主要应用Node.js 实现的RTSP(结合ffmpeg)/RTMP/HTTP/WebSocket/HLS/DASH流媒体服务器 特性 跨平台 ...

  5. 2-5-NFS服务器配置和autofs自动挂载-配置Samba服务器配置现实文件共享

    大纲: NFS服务器运行原理 实战配置NFS服务器 配置Samba服务器配置现实文件共享 ----------------------------------------------- 问题: # 怎 ...

  6. Nim游戏与SG函数 ——博弈论小结

    写这篇博客之前,花了许久时间来搞这个SG函数,倒是各路大神的论文看的多,却到底没几个看懂的.还好网上一些大牛博客还是性价比相当高的,多少理解了些,也自己通过做一些题加深了下了解. 既然是博弈,经典的N ...

  7. C# RedisRateLimiter

    public class RedisRateLimiter { private static Logger LOG = LogManager.GetLogger("redis-limiter ...

  8. java和python互相调用

      java和python互相调用  作者:xuaijun  日期:2017.1.1 python作为一种脚本语言,大量用于测试用例和测试代码的编写,尤其适用于交互式业务场景.实际应用中,很多网管系统 ...

  9. Ansible 小手册系列 六(Patterns 匹配模式)

    Patterns 是定义Ansible要管理的主机.但是在playbook中它指的是对应主机应用特定的配置或IT流程. 命令格式 命令行 ansible <host-pattern> [o ...

  10. C++多线程2.beginthread

    C++ 多线程2 beginthread 启动线程知识 20131021 Reference: http://blog.csdn.net/laoyang360/article/details/7720 ...