一個解決在非UI線程中訪問UI 異常的小方法


寫 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(); }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM