【问题标题】:Running an async task and invoking winform control运行异步任务并调用 winform 控件
【发布时间】:2017-07-07 04:31:33
【问题描述】:

如果有这个代码:

Task[] tasks = new Task[3];


int index = 0;
foreach (KeyValuePair<string, int> packageId in PackageIds)
{
    await Task.Run(() => _logger.Log(packageId.Key));

    tasks[index] = Task.Factory.StartNew(() =>
    {
        Log(packageId.Key);
    });
    index++;
}

Task.WaitAll(tasks);
_logger.Log("all done");

这是日志函数:

private void Log(string message)
{
    ListViewItem lv = new ListViewItem
    {
        Text = $"{DateTime.Now:dd-MM-yyyy hh:mm:ss}"
    };
    lv.SubItems.Add(message);

    if (listView1.InvokeRequired)
        Invoke(new Action(() => Log(message)));
    else
        listView1.Items.Add(lv);
}

当我运行它时,我可以看到代码尝试调用 listView1。但在那之后,应用程序挂起并且根本不继续。当我删除 Log() 并再次运行它时,它可以完美运行。

如何使用日志记录运行此代码?

【问题讨论】:

  • 你显然有无限循环/递归 - Log 函数将永远调用自己,以防listView1.InvokeRequired = true
  • 如何使用日志运行此代码? - 您试图通过从另一个线程记录消息来实现什么?为什么不在 await 之后在 foreach 循环内的 listview 中简单地添加日志消息?
  • 正如现在的代码一样,绝对没有理由使用任务。一切仍然在 UI 线程上完成。
  • 如果没有好的minimal reproducible example,就不可能知道如何最好地处理您的方案。也就是说,您发布的代码是各种错误的。最大的问题(最有可能导致挂起)是您调用Task.WaitAll(),而(显然)在其他线程中执行的代码最终将要调用Control.Invoke() 并使用您正在阻塞的线程。除此之外,根本不清楚你为什么要打扰Task 的东西。它似乎没有任何好处,只会让你感到困惑。

标签: c# winforms asynchronous task


【解决方案1】:

您正在以危险的方式使用 InvokeRequiered/Invoke 模式。

问题是您使用InvokeRequired 来检查您的线程是否可以从ListView1 调用函数。如果没有,则不要使用 Invoke 调用 ListView1 函数,而是调用自己的函数(this.Log)。

实现此模式的正确方法是检查是否需要调用是针对您自己的表单。问:this.InvokeRequired 而不是 listview1.InvokeRequired:

class MyForm : Form
{
    ...

    private void MyEventHandler(object sender, ...)
    {
        if (this.InvokeRequired)
        {
            Invoke(new MethodInvoker( () => this.MyEventHandler(sender, ...));
        }
    }
    else
    {
        ProcessMyEvent(...);
    }

如果您使用调试器单步执行此函数,您将看到调用是必需的,因此您再次调用相同的函数,之后不再需要调用。

顺便说一下,StackOverFlow: MethodInvoker vs Action for Control.BeginInvoke中给出了使用MethodInvoker而不是Action的原因

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 2010-10-25
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    • 2018-08-18
    相关资源
    最近更新 更多