【问题标题】:UI only partly responsive while running tasks and updating uiUI 在运行任务和更新 ui 时仅部分响应
【发布时间】:2022-01-20 09:07:08
【问题描述】:

我有以下 ui -

应测试与 crm 的每条线路连接。这是在单独的线程中完成的。

最后一列更新crm系统连接的测试状态。

问题在于,在线程运行和更新 ui 期间,ui 仅部分响应,即 我想在更新时点击这些行。

这是我的代码:

private async void btnTestAllConnections_Click(object sender, EventArgs e)
        {
            await TestConnectionsAsync();
        }

        private async Task TestConnectionsAsync()
        {
            try
            {
                int idxConn = columnLookup[ColumnIndex.Connection].Index;

                if (lvInitParameters.Items.Count == 0)
                    return;

                ManagedConnection connection = null;

                btnTestAllConnections.Visible = false;
                btnTestConnection.Visible = false;
                panel2.Enabled = false;
                panel3.Enabled = false;
                tableLayoutPanel1.Enabled = false;
                btnCancelTest.Visible = true;

                List<Task> tasks = new List<Task>();

                var cts = new CancellationTokenSource();
                CancellationToken token = cts.Token;

                foreach (ListViewItem lvi in lvInitParameters.Items)
                {
                    InitParamProxy currentProfile = (InitParamProxy)lvi.Tag;

                    lvi.SubItems[idxConn].Text = "Testing...";

                    Task<bool> result =null;

                    try
                    {

                        result = Task.Run(
                  () =>
                 {
                     try
                     {
                         connection = currentProfile.ManagedConnection;
                         return connection?.ConnectionSuccess ?? false;
                     }
                     catch (Exception ex)
                     {
                         // crm exception
                         return false;
                     }
                 }, token);
                        if (token.IsCancellationRequested)
                        {
                            Console.WriteLine("\nCancellation requested in continuation...\n");
                            token.ThrowIfCancellationRequested();
                        }


                        ListViewItem testItem =
                        items.Where(si => ((InitParamProxy)lvi.Tag).ProfileKey.Equals(((InitParamProxy)si.Tag).ProfileKey)).SingleOrDefault();


                        lvi.SubItems[idxConn].Text = (result.Result) ? "Success" : "Fail";

                        if (testItem != null)
                            testItem.SubItems[idxConn].Text = (result.Result) ? "Success" : "Fail";
                    }
                    catch
                    {
                        ListViewItem testItem =
                            items.Where(si => ((InitParamProxy)lvi.Tag).ProfileKey.Equals(((InitParamProxy)si.Tag).ProfileKey)).SingleOrDefault();

                        lvi.SubItems[idxConn].Text = "Canceled";

                        if (testItem != null)
                            testItem.SubItems[idxConn].Text = "Canceled";
                    }

                    tasks.Add(result);
                }

                Task.WaitAll(tasks.ToArray());

                btnTestAllConnections.Visible = true;
                btnTestConnection.Visible = true;
                panel2.Enabled = true;
                panel3.Enabled = true;
                tableLayoutPanel1.Enabled = true;
                btnCancelTest.Visible = false;
            }
            catch (Exception)
            {

            }
        }

【问题讨论】:

    标签: c# user-interface task


    【解决方案1】:

    在你的方法结束时

    Task.WaitAll(tasks.ToArray());
    

    这将阻塞直到所有任务完成。你应该改用WhenAll

    await Task.WhenAll(tasks.ToArray());
    

    您还在几个地方使用了result.Result,这也会阻塞。这应该替换为等待任务,即await result

    【讨论】:

    • 感谢 Jonas,但 ui 仍然冻结...
    • @user17582358 我已经修改了答案
    • @user17582358 如果从 IDE 运行,您可以暂停代码执行,然后评估您的线程所在的位置。这可以提供一个线索,即 UI 代码的哪一部分仍然是问题。
    • 单步执行代码一切正常(listview 项目的值,线程正确结束),但 ui 只是闪烁并且不刷新。点击 ui 会导致一段时间无响应...
    • @user17582358 UI 只会在更新 UI 的代码运行后更新。如果您使用的是 winforms,您可能需要插入 invalidate 调用来强制重绘。一般来说,我会建议使用性能分析器,它应该会显示 UI 何时被阻止以及原因。
    猜你喜欢
    • 2016-09-12
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2018-06-03
    • 2017-01-26
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    相关资源
    最近更新 更多