簡體   English   中英

為什么我只能從BackgroundWorker訪問某些UI控件屬性?

[英]Why can I access only some UI control properties from BackgroundWorker?

我有一個簡單的Windows Forms應用程序,該應用程序使用幾個BackgroundWorker元素在后台執行操作。 在開發過程中,我注意到我能夠執行諸如在DoWork()方法中獲取和設置Label的.Text值之類的操作,但是卻無法獲取DrowDownList的值。

我的印象是BackgroundWorker不應該進行任何UI交互,此規則是否有例外?

我不是在尋找從BackgroundWorker更新UI的建議,我更好奇是否可以使用快捷方式,例如直接從BackgroundWorker更新ToolStripStatusLabel的文本。

這是一個簡單的示例,工作程序1直接更新UI,而工作程序2使用進度更新:

private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

private void button2_Click(object sender, EventArgs e)
{
    backgroundWorker2.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    toolStripStatusLabel1.Text = "Performing task 1...";
    performTaskOne();
    toolStripStatusLabel1.Text = "Task 1 done.";

    toolStripStatusLabel1.Text = "Performing task 2...";
    performTaskTwo();
    toolStripStatusLabel1.Text = "Task 2 done.";

    toolStripStatusLabel1.Text = "Performing task 3...";
    performTaskThree();
    toolStripStatusLabel1.Text = "Task 3 done.";
}

private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
    backgroundWorker2.ReportProgress(0, "Performing task 1...");
    performTaskOne();
    backgroundWorker2.ReportProgress(20, "Task 1 done.");

    backgroundWorker2.ReportProgress(40, "Performing task 2...");
    performTaskTwo();
    backgroundWorker2.ReportProgress(60, "Task 2 done.");

    backgroundWorker2.ReportProgress(80, "Performing task 3...");
    performTaskThree();
    backgroundWorker2.ReportProgress(100, "Task 3 done.");
}

private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    string status = (string)e.UserState;
    toolStripStatusLabel1.Text = status;
}

private void performTaskThree()
{
    Thread.Sleep(1000);
}

private void performTaskTwo()
{
    Thread.Sleep(1000);
}

private void performTaskOne()
{
    Thread.Sleep(1000);
}

您不應該從后台線程訪問或更新UI。 期。

這是大多數UI元素的功能 ,如果沒有從UI線程訪問它們,它們將檢測到它們並主動拋出異常,以便開發人員在第一次運行代碼時立即意識到他們不正確地訪問了控件。

並非所有的UI控件,也不是UI控件的所有方面都具有此功能 特定地將某些成員記錄為可以從非UI線程安全使用的對象的成員(例如,顯然可以從非UI線程使用控件的Invoke方法;這就是它存在的原因)。 對於那些未記錄的內容,不應在非UI線程中使用它們。

僅僅因為它在您第一次使用時不會崩潰並不意味着它會起作用。 這意味着整個代碼中可能存在競爭條件,這些競爭條件可能會根據其他線程同時訪問共享資源的情況而出現。 當您對其進行測試時,它可能會起作用,也可能會反復起作用,但是,如果只是在適當的情況下發生,則可能會發生各種不良情況。 也許程序會崩潰,也許數據將被破壞,也許事情將不起作用,或者可能會發生各種奇怪的事情。 如果將這樣的代碼發布給客戶,突然之間,您會遇到很多不同的人,它們以許多不同的意外方式以及在非常不同類型的環境中執行代碼,那么您遇到問題的機會就不會遇到在您自己的測試中急劇上升。

因此,請花點時間確保僅從UI線程訪問UI控件。

值得一提的是,它完全有助於單獨組織代碼,以使UI和表示邏輯與業務邏輯分離。 混合它們會導致難以推理,理解,維護或更改的應用程序。

暫無
暫無

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

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