在主线程陷入while循环(或Task.WaitAll)时编辑GUI

本文关键字:WaitAll Task GUI 编辑 线程 循环 while | 更新日期: 2023-09-27 18:22:09

所以,经过长时间的咒骂和放弃希望,我(几乎)一切都好了。

我有一个GUI,它显示连接地址列表和消息列表。通常情况下,当我关闭连接器(断开与地址的连接)时,我会写一条消息说:"断开与x地址的连接"。然而,正如您将从这些方法中看到的那样,在处理应用程序时,我不能使用调度器来写入该消息(this.ModuleConnections.Remove(address);触发消息的写入,并从列表中直观地删除它)。

private void CloseConnector(string address)
{
    Task task = new Task(() =>
    {
        var moduleConnection = this.ModuleConnections[address];
        moduleConnection.ModuleConnector.Dispose();
        if (mDisposed == true)
        {
            ApplicationSupport.Dispatcher.Invoke(
                DispatcherPriority.Background,
                new Action(() =>
                {
                    this.ModuleConnections.Remove(address);
                }));
        }
    });
    task.Start();
    if (mDisposed == true)
    {
        mTasks.Add(task);
    }
}
protected virtual void Dispose(bool disposing)
{
    // Dispose managed resources.
    if ((mDisposed == false) && (disposing == true))
    {
        mTasks.Clear();
        mDisposed = true;
        CloseConnectors();
        Task.WaitAll(mTasks.ToArray());
    }
}

我无法使用调度程序,因为Task.WaitAll会停止线程。如果线程停止,则调度程序无法执行this.ModuleConnections.Remove(address);,这将导致任务未完成,如果任务未完成task.WaitAll将不会释放线程。这是一个很大的问题。

如果没有task.waitall,我将处理大量的对象和未找到密钥的异常以及其他令人讨厌的事情,这些事情使一些线程保持运行,因此应用程序不会完全关闭。

但现在,当它关闭时,GUI会冻结(看起来像崩溃了)几秒钟,然后(当task.waitall完成时)它会关闭窗口,整个应用程序也会正确关闭。

我想要的是仍然能够更新我的消息列表,并显示断开连接的地址。

只是为了澄清
我需要CloseConnector方法中的Task,因为关闭连接器(dispose)会使其断开连接,它需要等到收到来自另一端的消息后才能继续代码。如果我一个接一个地运行这个程序,它将需要几分钟,与我现在所做的并行,它只需要几秒钟。

在主线程陷入while循环(或Task.WaitAll)时编辑GUI

我看到的第一件事是,如果您想用WaitAll() minhod对它们进行调优,则不需要为任务调用Start()方法。此外,如果您想一次运行一个任务,最好使用Task.Run(),它将Expression作为参数。这种情况下的区别在于,Run()强制您的任务立即开始,而Start()不能保证您的任务现在就开始——它只是计划从TaskScheduler开始。顺便说一下,Wait()的工作方式与相同

最后,检查您的this对象——此时这是什么?它不是空的吗?也许可以尝试使用闭包并将您的dispatcher作为arg

希望对有所帮助