c# - 在 Form.Dispose() 方法中安全调用

标签 c# .net multithreading winforms invoke

我有一个 ApplicationContextForm .各种异步通信和定时线程可能偶尔需要重启应用程序,但是在我重启之前我必须手动处理 MyApplicationContext这需要释放新进程启动时立即需要的资源。

好像只是调用了Application.Restart()在这种情况下,处理资源的速度不够快。

在对 MyApplicationContext.Dispose() 的调用中随后调用 base.Dispose(disposing)最终调用 Form.Dispose()方法,并且因为这可能源自各种线程,所以我看到发生了跨线程操作异常。

/// MyApplicationContext.requestRestart()
private void requestRestart()
{
    this.Dispose(); // dispose of applicationcontext
    Application.Restart();
}

导致...

/// MyApplicationContext.Dispose(bool)
protected override void Dispose(bool disposing) 
{
    /// dispose stuff
    base.Dispose(disposing);
}

导致...

/// MainForm.Dispose(bool)
protected override void Dispose(bool disposing)
{
    /// dispose stuff
    base.Dispose(disposing);
}

可以从任何线程调用。

Invoke安全吗? Form 上覆盖的处置处理程序像这样的 UI 线程?

protected override void Dispose(bool disposing)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action(() => Dispose(disposing)));
    }
    else
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
}

最佳答案

不,从 Dispose() 实现中调用 Invoke() 是不安全的。

好吧,既然我已经说过了:当然,你可能会侥幸逃脱。但这是一个非常糟糕的主意,它确实会导致真正的问题。

Dispose() 方法应该简单。它不应该访问托管对象,并且应该很快完成。调用 Invoke() 可能会导致不确定的延迟,具体取决于程序中发生的其他情况,甚至会导致完全死锁。

除此之外,Dispose() 方法中的一个重要规则是不访问托管对象。至少,您的实现需要首先检查 disposing,以确保您不会在从终结器调用时尝试调用 Invoke()。此外,处置当前用于调用 Invoke() 方法的对象也绝对不是一个好主意。如果您真的必须使用跨线程调用,正确的方法是检索当前对象的 SynchronizationContext 并使用它而不是调用 Control.Invoke().


但实际上,此处正确的做法是修复重启逻辑,以便整个处理操作发生在拥有要处理的对象的 UI 线程中。您的对象不是负责将执行移动到正确线程的对象; 使用那些对象的代码应该改为。当涉及到 Form 类的代码时,您应该已经确保代码在拥有该对象的 UI 线程中执行。

关于c# - 在 Form.Dispose() 方法中安全调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35736167/

相关文章:

c# - 如何在 scriptcs csx 脚本中定义扩展方法

c# - 如何在不暂停的情况下移动 gif 动画?

c# - 在不尝试发送电子邮件的情况下检查邮件服务器是否使用 SSL

.net - 无法让 Left JOIN linq 查询工作!

c# - Task.Run(()=> DoWorkAsync()) 和 new Thread(async()=> DoWorkAsync()); 之间的区别

c# - 如何在 ASP.NET MVC 4 中使用 Ninject 从 Web.config 绑定(bind)设置?

c# - 如何在 foreach 循环中创建动态 src?

c# - C# 如何从 .NET Framework 中分离出来?

java - 从技术上讲,什么是数据库连接?

objective-c - 使用Realm数据填充UITableView(表格)?