簡體   English   中英

我將如何使用Background Worker來使GUI響應?

[英]How would I use Background Worker to get my GUI to respond?

我制作了一個只有一個按鈕的簡短程序。 當按下按鈕時,將執行功能A,該功能也將使用功能B和功能C。 在functionA內部是一個循環,循環執行functionB和functionC X次。 在每個循環的末尾,進度條將增加1。在功能A的開始處,在循環前,有一個Web服務將從網站上提取數據,並將其傳遞給B和C進行處理(將數據文件進行處理並保存到磁盤)。

我的問題是,一切正常,但是當functionA仍在運行時,GUI卡住了,因此我無法關閉/最小化/拖動周圍的窗口,我必須等到A完成之后。 我進行了研究,他們說我應該使用BackgroundWorker,但是作為一名新程序員,我不知道如何使用它。 有人可以給我一種簡單的使用方法嗎?

進度條可以很好地加載,但是僅僅是在函數運行時,整個窗口都被凍結了,所以我想要它,以便我可以在程序運行時四處移動窗口,而不必等到函數完成為止。

謝謝!

像下面這樣異步調用函數,它不會凍結UI。

private async void BeginProcessingAsync(Data d)
{
    //Execute the long running task asynchronously
    await Task.Run(() =>  functionA(d));

    //Anything after the await line will be executed only after the task is finished.
    anotherFunction(d); // if you have one..
}

要運行任務,只需調用BeginProcessingAsync(d); 另外,請注意:如果使用的是.NET的較新版本,則可能必須使用await Task.Factory.StartNew(() => functionA(d)); 代替上面

總體而言,您需要確保您的GUI不會從其他線程更新。 而是,消息應轉到線程安全的位置。 例如 ,您可以將線程構建到類似數據庫的對象中,並讓GUI使用計時器來查找更新的數據標志。

這里有一個使用委托的問題,其中有更多細節

在我看來, 馬克的答案是最簡單,最好的:

///...blah blah updating files
string newText = "abc"; // running on worker thread
this.Invoke((MethodInvoker)delegate {
    someLabel.Text = newText; // runs on UI thread
});
///...blah blah more updating files

Dotnet Perls

后台工作程序使線程易於在Windows窗體中實現。 需要在另一個線程上完成繁重的任務,因此UI不會凍結。 完成任務后,有必要發布消息並更新用戶界面。

另外,如果您使用的是C#5,請從MSDN中查看基於任務的異步模式 (TAP)。

基於任務的異步模式(TAP)基於System.Threading.Tasks命名空間中的System.Threading.Tasks.Task和System.Threading.Tasks.Task類型,用於表示任意異步操作。 TAP是新開發的推薦異步設計模式。

暫無
暫無

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

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