簡體   English   中英

為什么我不能從另一個線程訪問UI控件的屬性?

[英]Why can't I access properties of an UI control from another thread?

我讀到不可能從另一個線程(不僅是GUI,而且還訪問所有2個不同的線程)訪問UI元素,並且看到了如何解決該問題的代碼,但是沒有找到解釋為什么我不能這樣做?

MSDN不允許這樣做的原因:

訪問Windows Forms控件本質上不是線程安全的。 如果您有兩個或多個線程來操縱控件的狀態, 則可以將控件強制變為不一致的狀態 其他與線程相關的錯誤也是可能的,包括競爭條件和死鎖。 確保以線程安全的方式完成對控件的訪問非常重要。

因此從技術上講,我是有可能的(也許他們是在設計時將其遺漏了),但問題是Microsoft的基礎代碼不是線程安全的。 這可能與Windows的內部工作方式有關,並且Win32 UI模型中缺乏線程安全性。

您不能從GUI線程(主線程)以外的任何其他線程對GUI進行更改。 話雖如此,如果您想從另一個線程更改控件,則可以從任何線程讀取控件(文本框等)中的數據,而無需使用以下操作:

textBox1.Invoke((MethodInvoker)(() =>
{
    textBox1.Text = "text changed from another thread";
}));

不利的一面是,現在您正在調用的線程被阻塞,直到完成對文本框的更改為止。 如果您不經常從線程中更新控件,但這不是問題,但是如果您想經常執行此操作,則需要創建一個第3個線程來處理更新,具體取決於工作線程在做什么。 像這樣

List<string> list = new List<string>();
Thread workThread = new Thread(dowork =>
{
    //random work
    for(int a = 0; a< 1000000;a++)
    {
        list.Add(a+" iteration");
        Thread.Sleep(10);
    }
});
workThread .Start();
bool updateThreadWorking = true;
Thread updateThread = new Thread(dowork =>
{
    while(updateThreadWorking)
    {
        while(list.Count > 0)
        {
            listBox.Invoke((MethodInvoker)(() =>
                listBox.Items.Add(list[0]);
            }));
            list.RemoveAt(0);
        }
        Thread.Sleep(200);
    }
});
updateThread .Start();

現在,工作線程正在全速運行,而不會被UI阻塞,並且UI仍在更新當前狀態

暫無
暫無

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

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