gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 21:51:20 24 4
gpt4 key购买 nike

我有一个 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com