寫 WPF 的童鞋可能都會碰到 在非UI線程中訪問 UI 異常的問題。這是為了防止數據不一致做的安全限制。
子線程中更新UI還要交給主線程更新,引用滿天飛,實在是麻煩。
接下來,我們推出一個可以稱之為框架的解決方案(拍磚的時候輕點)。
在 C# 中 微軟好像沒有給出直接判斷當前線程是否是主線程的方案,至少我是沒找到。
如果您有更好的解決方案請留言哦?。。。?/p>
/// <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); }}
擴展線程類,用于判斷當前方法是否是主線程,判斷下指定線程是否是哥當初賞賜了名字的那個線程。
好了,到這里就能判斷當前線程是否是主線程了。
/// <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();}
新聞熱點
疑難解答