UI 无响应,直到操作完成 [英] UI unresponsive until action is complete

查看:24
本文介绍了UI 无响应,直到操作完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定标题是否很好地描述了这个问题.基本上我拥有的是一个 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:

  1. 打开应用
  2. 查看 ListView 控件中的文件列表
  3. 点击上传按钮
  4. ListView 中列出的文件被上传;每次成功上传后,ListView 都会更新以显示'成功'
  5. 上传所有文件后,操作停止.

我的问题是,单击上传按钮后,用户界面几乎没有响应,直到操作完成.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 和方便的 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 无响应,直到操作完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆