一个解决在其它的线程中访问UI 异常的小方法_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 一个解决在其它的线程中访问UI 异常的小方法

一个解决在其它的线程中访问UI 异常的小方法

 2015/1/4 16:40:51  六Yue雪  程序员俱乐部  我要评论(0)
  • 摘要:写WPF的童鞋可能都会碰到在子线程中访问UI异常的问题。这是为了防止数据不一致做的安全限制。子线程中更新UI还要交给主线程更新,引用满天飞,实在是麻烦。接下来,我们推出一个可以称之为框架的解决方案(拍砖的时候轻点)。一:解决判断当前线程是主线成的问题在C#中微软好像没有给出直接判断当前线程是否是主线程的方案,至少我是没找到。///<summary>///Lyx线程框架类///</summary>publicclassLyxThreadFrame{///<
  • 标签:方法 解决 一个 线程 异常

写 WPF 的童鞋可能都会碰到 在子线程中访问 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 类在.Net 下是老子的身份,所有委托均继承至它。 在这里我们扩展了 Delegate

这里有个 Application 类,我们程序中的 App 就是基础了这个。它是程序的入口点。 

 

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

 

示例:

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

 

发表评论
用户名: 匿名