[英]UI unresponsive until action is complete
我不確定標題是否很好地描述了這個問題。 本質上,我擁有的是一個 WinForm 應用程序,它將文件夾中的文件列表檢索到 ListView,然后單擊一個按鈕以通過 FTP 將它們上傳到遠程服務器。
從功能上講,該應用程序按預期工作:
我的問題是,單擊上傳按鈕后,用戶界面在操作完成之前幾乎沒有響應。 ListView 在每個文件上傳時按預期更新,甚至保持活動行的焦點。 這是處理文件的 for 循環。 一點背景 - 在下面的代碼摘錄中,每個 for... 循環處理 2 個文件 - 主文件是 ListView 中唯一顯示的文件。 每個循環中的第二個文件是一個觸發器文件,在其主要文件發送后發送,即:.primary、.trigger。 必須發送這兩個文件才能注冊成功。 如果主文件沒有對應的觸發文件,則無法在 ListView 中進行上傳。
foreach (ListViewItem item in lvSourceFiles.Items)
{
int rowIndex = item.Index;
string fileName = item.SubItems[2].Text;
lvSourceFiles.EnsureVisible(rowIndex);
transferStatus = "Failed"; // Set this as a default
// Transfer the source file first
transferResult = session.PutFiles(readyFile, destFile, false, transferOptions);
// Throw on any error
transferResult.Check();
// If the source file transfer was successful, then transfer the trigger file
if (transferResult.IsSuccess)
{
transferResult = session.PutFiles(triggerFile, destFile, false, transferOptions);
transferResult.Check();
if (transferResult.IsSuccess)
{
transferStatus = "Success";
}
}
UpdateResultsToListView(lvSourceFiles, rowIndex, fileName, transferStatus);
}
這是我需要實現某種異步功能的情況,還是有更好的方法來做到這一點,以便 UI 在上傳過程中不會凍結? 本質上,我希望能夠在上傳運行時與表單進行交互,例如有一個取消按鈕來停止上傳。 就目前而言,在工作完成或終止應用程序之前,我無法對表單進行任何操作。
謝謝,詹姆斯
您可以使用 async/await 和方便的Task.Run
方法將長時間運行的操作卸載到ThreadPool
線程:
transferResult = await Task.Run(() => session.PutFiles(readyFile, destFile, false, transferOptions));
...和:
transferResult = await Task.Run(() => session.PutFiles(triggerFile, destFile, false, transferOptions));
您還應該在事件處理程序中添加async
修飾符,以啟用await
運算符。
重要提示:避免在卸載方法中執行任何與 UI 相關的操作。 如果要在操作期間與 UI 進行通信,例如進行進度報告,請使用Progress<T>
類。
您不能在 GUI 線程上進行冗長的操作。 在后台線程上執行它們。
@Theodor 的回答正確地表明您可以將PutFiles
移動到線程池。
另一種選擇是將所有上傳邏輯移動到線程池,並使用Control.Invoke
回調到主線程,僅用於 GUI 更新。
有關完整示例,請參閱 WinSCP 文章在 WinForms ProgressBar 上顯示 FTP/SFTP 傳輸進度。
選擇更適合您的選項。 我相信我的方法對於沒有線程編程經驗的人來說更容易掌握。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.