簡體   English   中英

我可以從后台線程更新UI,為什么?

[英]I can update UI from background thread, why?

大家都知道,不允許從后台線程更新UI(或不?)

我做了一個小實驗。 這是一段代碼:

var thread = new Thread(() => progressBar1.Increment(50));
            thread.IsBackground = true;
            thread.Start();
            thread.Join();

我將此代碼放在一些按鈕單擊處理程序中。 知道嗎? 我的進度條正在遞增...從后台線程。 現在我很困惑。 我不明白它是如何可能的以及我做錯了什么

我可以從后台線程更新UI,為什么?

最有可能的是,當您在調試器外部運行時,您可以這樣做。 這是因為該保護由Control.CheckForIllegalCrossThreadCalls屬性控制。 我們來看看參考源

private static bool checkForIllegalCrossThreadCalls = Debugger.IsAttached;
public static bool CheckForIllegalCrossThreadCalls {
    get { return checkForIllegalCrossThreadCalls; }
    set { checkForIllegalCrossThreadCalls = value; }
}

如您所見,只有在調試時才會默認啟用此保護。

如果在Main方法中添加以下行(在Application.Run之前)

Control.CheckForIllegalCrossThreadCalls = true;

你的代碼將不再起作用。

大家都知道,不允許從后台線程更新UI

不是每個人都知道。 但這是事實。 從UI線程以外的線程更新大多數UI元素是錯誤的。

我不明白它是如何可能的

你把一堆沙子倒進汽車的油底殼里。 你不應該這樣做。 那么你怎么可能這樣做呢? 好像問一個奇怪的問題,不是嗎?

汽車是否需要阻止你這樣做? 不是。當您這樣做時,發動機是否需要停止運轉? 不會。發動機最終會破裂嗎? 大概。 但不一定。

設計你的汽車的工程師認為你不會做錯事,所以他們沒有建立任何安全系統來防止或發現這個問題。

我究竟做錯了什么?

您正在從后台線程更新UI。 不要那樣做。 但運行時不需要提供防止或檢測錯誤的安全系統。 當你做一些你不應該做的事情時,不需要產生錯誤。 如果它想要或不想,它可以自行決定。

或者,這樣考慮一下。 假設您正在實現運行時,以便它具有您認為具有的屬性:運行時將始終檢測到錯誤的跨線程調用並在發生時產生錯誤。 這是一個功能。 有人必須設計,編寫,測試和維護該代碼。 代碼是什么樣的,與它相關的所有成本是多少?

就像varocarbas所說,你放入設計器的任何組件都會拋出Cross thread異常。

在線程之間訪問你需要使用invke,beginInvoke。

試着跑

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s1,e1) => 
{
    textBoxt1.Text = "foo";  // Exception here
} 
bw.RunWorkerCompleted += (1s, e1) =>
{
    textBoxt1.Text = "foo";  // No exception here off UI thread
}
bw.RunWorkerAsync();

而是替換

bw.DoWork += (s1,e1) => 
{
    this.Invoke((MethodInvoker) delegate 
   {
        textBoxt1.Text = message;
   });  // No Exception now
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM