【问题标题】:Winforms asynchronous task, run multiple threads at once without blocking UIWinforms异步任务,一次运行多个线程不阻塞UI
【发布时间】:2016-12-16 11:41:50
【问题描述】:

我是来自网络的 Winforms 的新手,我正在努力了解异步调用。

我有一个下拉列表,我想调用一些方法来更新我页面上的 3 个选项卡。我想异步执行这些操作,这样它就不会阻塞用户界面,并在每个选项卡上放置一个“正在加载...”消息并相互独立地加载它们,用户仍然可以单击每个选项卡并且查看加载进度。

我有以下内容,但是这仍然锁定了 UI,有人可以为我指出错误的正确方向吗?

这是我的下拉事件处理程序

    private async void ddlRoles_SelectedIndexChanged(object sender, EventArgs e)
    {
        await Task.Run(async () =>
        {
            await setTab1();
        });

        await Task.Run(async () =>
        {
            await setTab2();
        });

        await Task.Run(async () =>
        {
            await setTab3();
        });
    }

这是我想要异步运行的任务之一的示例。

    private async Task setTab1()
    {
        if (tabl1Panel.InvokeRequired)
        {
            this.Invoke(new MethodInvoker(async delegate ()
            {
                await setTab1();
            }));
            return;
        }

        // LONG RUNNING CODE HERE...
    }

【问题讨论】:

  • @x... 不,不是这样。递归不会导致任何 UI 问题。在 UI 线程上等待一个任务,该任务本身试图在已经阻塞的 UI 线程(使用 Invoke)上运行代码是问题
  • 不要使用线程,你不太可能做任何 CPU 密集型工作。 “Loading”这个词意味着你在做 I/O,在这种情况下你应该做异步单线程。

标签: c# multithreading winforms asynchronous task


【解决方案1】:

您用于运行 setTab1() 的 Invoke 调用意味着代码在 UI 线程上运行,这就是 UI 锁定的原因。

尝试在 setTab1() 中尽可能多地不使用 Invoke(),并且仅在获得所需的所有数据后才使用 Invoke() 运行代码以更新 UI。

【讨论】:

  • 好的...这就是您对每个选项卡所说的内容,在没有调用的情况下在单独的异步方法中完成尽可能多的工作,然后调用单独的方法来更新 UI完成了吗?
  • @user3284707 这就是每个教程和指南所说的。最简单的例子是例如var result=await someHeavyFunc(); updateUi();。如果您想发布定期进度更新,请使用 IProgress<T>Progress<T> 实现将消息从任务发送到 UI
  • 非常感谢,我看看能不能搞定:)
  • 这解决了我的问题..谢谢你的回答!
猜你喜欢
  • 2017-07-07
  • 2014-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-29
相关资源
最近更新 更多