【问题标题】:UI not responsive during frequent updates from background workerUI 在后台工作人员频繁更新期间没有响应
【发布时间】:2015-10-28 05:46:15
【问题描述】:

我正在开发一个 Windows 窗体应用程序,它逐行读取文件[在后台工作线程中] 并填充数据网格视图 [使用 BeginInvoke]。 完成此操作后,UI 变得无响应(无法取消/退出或拖动窗口),但我可以看到 datagridview 正在更新。 我所知道的是,这是因为消息被泵入消息队列,其优先级高于用户输入消息。

有没有一种方法可以让 UI 仍然响应用户输入?

【问题讨论】:

  • 您能否发布有关您的表单申请的更多详细信息?比如代码 sn-p 什么的?

标签: c# multithreading datagridview backgroundworker message-pump


【解决方案1】:

由于您使用的是BeginInvoke,因此您在 UI 线程上执行操作。如果您逐行阅读并一次附加每一行,那么在那儿有一个后​​台工作人员并没有真正的帮助。

如果需要在加载时更新视图,您应该一次添加所有内容,或者至少以块的形式添加。通常只加载然后一次性添加数据会更快。

【讨论】:

  • 数据非常庞大(50,000 + 条记录),因此用户应该能够在导入数据时看到进度。此外,读取是在后台线程中完成的,BeginInvoke 只是被使用更新用户界面。
  • @deXter 正如 Sami 所建议的那样,以块/批次而不是 1-by-1 的方式进行。否则,您只会为您的应用程序淹没 Windows 消息泵,从而使一切都变慢,包括绘画和鼠标。
  • @Micky 如果我以块的形式从后台工作人员发送数据,可以说每个记录 100 条。当这 100 条记录被填充到 datagridview 中时,它不会挂起 UI 线程吗?
  • @deXter 告诉网格停止更新,添加1000条记录并说“好的,你可以更新”比一条一条要快得多。
  • @deXter 不要错误地认为来自工作线程的BeginInvoke 调用实际上是在更新UI——它不是。它通知 UI 线程代表工作人员执行操作。非 STA 工作线程无法更新 UI
【解决方案2】:

尝试使用任务库而不是使用BackgroundWorker(Task比BackgroundWorker更好),下面的sn-p可以帮助

    CancellationTokenSource tokenSource2 = new CancellationTokenSource();
    CancellationToken ct;
    public MainWindowViewModel()
    {      

        ct = tokenSource2.Token;
        Task.Factory.StartNew(PopulateDataGrid, ct);
    }

    /// <summary>
    /// 
    /// </summary>
    private void PopulateDataGrid()
    {           
        for (int i = 1; i < 10000; i++)
        {
            if (!ct.IsCancellationRequested)
            {

                 ///Populate Your Control here                   
            }
            else
            {
                break;
            }
        }
    }

    public void OnCancelCLick()
    {
        tokenSource2.Cancel();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    • 1970-01-01
    相关资源
    最近更新 更多