問題描述
我不確定標題是否很好地描述了這個問題.基本上我擁有的是一個 WinForm 應用程序,它從文件夾中檢索文件列表到 ListView 中,然后單擊一個按鈕通過 FTP 將它們上傳到遠程服務器.
I'm not sure if the Title is a good description of this issue or not. Essentially what I have is a WinForm app that retrieves a list of files from a folder into a ListView, then a button is clicked to upload them via FTP to a remote server.
從功能上講,該應用按預期運行:
Functionally speaking, the app works as expected:
- 打開應用
- 查看 ListView 控件中的文件列表
- 點擊上傳按鈕
- ListView 中列出的文件被上傳;每次成功上傳后,ListView 都會更新以顯示'成功'
- 上傳所有文件后,操作停止.
我的問題是,單擊上傳按鈕后,用戶界面幾乎沒有響應,直到操作完成.ListView 會在每個文件上傳時按預期更新,甚至保持活動行處于焦點.這是處理文件的 for 循環.一點背景 - 在下面的代碼摘錄中,每個 for...loop 處理 2 個文件 - 主文件是 ListView 中唯一顯示的文件.每個循環中的第二個文件是一個觸發器文件,在其主文件發送后發送,即:.primary、.trigger.這兩個文件都必須發送才能注冊成功.如果主文件沒有對應的觸發文件,則無法在ListView中上傳.
My issue is, after clicking the upload button the UI is pretty much unresponsive until the operation finishes. The ListView updates as expected as each file is uploaded and even keeps the active row in focus. Here is the for loop that processes the files. A little background - in the code excerpt below, each for...loop processes 2 files - the primary file is the only one that shows in the ListView. The 2nd file in each loop is a trigger file that is sent after its primary is sent, ie: .primary, .trigger. Both files have to send in order to register a success. If a primary file does not have a corresponding trigger file, it won't be available in the ListView for upload.
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 在上傳過程中不會凍結?本質上,我希望能夠在上傳運行時與表單進行交互,例如有一個取消按鈕來停止上傳.就目前而言,在作業完成或終止應用程序之前,我無法對表單執行任何操作.
Is this a situation where I need to implement some sort of asynchronous functionality, or is there a better way to do this so the UI doesn't freeze during the upload process? Essentially I want to be able to interact with the form while the upload is running, such as having a cancel button to stop the upload. As it stands, I can't do anything with the form until the job completes, or I terminate the app.
謝謝,詹姆斯
推薦答案
您可以通過使用 async/await 和方便的 ThreadPool 線程https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run" rel="nofollow noreferrer">Task.Run
方法:
You could offload the long-running operation to a ThreadPool
thread, by using async/await and the handy Task.Run
method:
transferResult = await Task.Run(() => session.PutFiles(readyFile, destFile, false, transferOptions));
...和:
transferResult = await Task.Run(() => session.PutFiles(triggerFile, destFile, false, transferOptions));
您還應該添加 async事件處理程序中的
修飾符,以啟用 await
運算符.
You should also add the async
modifier in the event handler, in order to enable the await
operator.
重要提示:避免在卸載方法中執行任何與 UI 相關的操作.如果您想在操作過程中與 UI 進行通信,例如對于 進度報告,使用 Progress<T>
類.
Important: Avoid doing anything UI related in the offloaded method. If you want to communicate with the UI during the operation, for example for progress reporting, use the Progress<T>
class.
這篇關于UI 無響應,直到操作完成的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!