C# 调用Application.Exit()后,应用程序仍在内存中运行
我正在构建的应用程序在使用C# 调用Application.Exit()后,应用程序仍在内存中运行,c#,memory,exit-code,C#,Memory,Exit Code,我正在构建的应用程序在使用application.Exit()关闭后仍在内存中运行(签入任务管理器)。由于这一点,当我在如上所述关闭它之后再次运行它时,我会得到“一次只运行一个实例”的错误。您能告诉我如何完全关闭我的应用程序吗?这似乎是一个Windows ap,您正在调用System.Windows.Forms.application.Exit(),但后台仍有一个线程在运行。你试过了吗 Application.ExitThread(); Environment.Exit(); 正如Jones
application.Exit()
关闭后仍在内存中运行(签入任务管理器)。由于这一点,当我在如上所述关闭它之后再次运行它时,我会得到“一次只运行一个实例”的错误。您能告诉我如何完全关闭我的应用程序吗?这似乎是一个Windows ap,您正在调用System.Windows.Forms.application.Exit(),但后台仍有一个线程在运行。你试过了吗
Application.ExitThread();
Environment.Exit();
正如Jonesy所提到的,如果进程是一个独立于当前正在运行的进程的应用程序,则可以终止该进程,并传入该进程的进程ID
为此,您需要使用System.Diagnostics.Process命名空间并循环当前运行的进程,以获得正确的pid,然后对该pid调用kill。有一次,当我出现异常行为时(在
应用程序.Exit()期间崩溃/冻结),我使用了
该函数位于System.Diagnostics
命名空间中,似乎比Kill()
更好,因为它不会强制它以相同的方式退出。因为使用了前台线程和Lybda Expression线程,所以线程将继续运行,直到最后一个前台线程终止。另一方面,当所有前台线程停止时,应用程序关闭。
这就是为什么应用程序不会等到后台线程完成,而是等到所有前台线程终止。
因此,在这种情况下,我们必须使用
Environment.Exit(Environment.ExitCode)代码>
这使内存得到了完美的管理,没有内存泄漏。如果进程仍处于挂起状态,则表示您没有正确处理资源
使用Application.Exit()
或要求系统执行Environment.Exit(0)
可能会在发生错误时记录在系统中,如果您只想关闭一个线程并保持应用程序运行,您最好知道如何正确关闭进程,而不是依赖Application.Exit()
,你必须知道如何收集那些垃圾
您可以重新实现Dispose
方法来处理服务、套接字、流,以及几乎所有具有.Dispose
可用的内容
public类MyClass:IMyClass,IDisposable
{
private bool_disposed=false;
// ...
public void Dispose()
{
处置(真实);
总干事(本);
}
受保护的虚拟void Dispose(bool disposing)
{
如果(_)返回;
如果(处置)
{
//处理您在此类中创建的内容
//其他课程也一样
//一些例子
/*
_webClient.Dispose();
_connector.DataAvailable-=ConnectorHasDataComing
_socket.Dispose();
_timer.Dispose();
_taskLogs.ForEach(x=>{
x、 Token.Cancel();
x、 Task.Wait();
x、 Task.Dispose();
});
*/
}
//处置本机事件
_这是真的;
}
如果您使用System.Threading.Thread
或System.Threading.Tasks.Task
或System.IO.MemoryStream
(或其他类型的流编写器/读取器),以及其他需要CancellationTokenSource
的流。如果您在处理类时在类中创建了ressource,请使用标记.Cancel()
方法,让它知道其父级正在被释放,并在调用.Dispose()之前等待它
当我的调试在关闭应用程序后仍然挂起时,我使用诊断工具发现了问题
如果使用CPU使用率,可以单击全部中断
,然后设置断点。
然后,您可以查看profiler并找到最重要的函数,您可能会发现表单已被释放,但有一个线程或任务调用表单上的字段
在我的例子中,我使用了一个filewriter,并在该类中实现了IDisposable,但它有时会使用.copyTo
在文件读取器和自身之间进行数据传输,因此它是挂起的,不会引发异常
单击其中一个事件后,单击转到源代码
并放置断点,您可能会看到存储代码的事件
否则,您可以在同一工具中使用选项卡内存使用量
拍摄快照并查看堆和对象差异,或者使用选项卡CPU使用量
并查看记录的配置文件。我发现我的copyTo
就是这样发布的
您还可以在运行应用程序时抛出所有异常
在处理时,确保没有人回忆起表单或其实例。
此外,如果您正在使用表单事件\u FormClosing
确保如果您有取消表单关闭的模式,则返回并设置e.cancel=true;
,但如果表单正在关闭,则不要设置e.cancel=true
。并且不要在您正在处理的\u FormClosing()
事件中调用this.Close()
之后,您可以.Dispose()
处理您的东西,但请确保没有Dispose方法像调用组件那样调用表单,因为它们正在被处理或已经被处理
对于使用黑客将var实例中的表单设置为在任何地方都可以访问该表单的人,不要处理它,否则您正在处理已处理的表单。您是否使用Microsoft.Office.Interop
?(例如Excel)您是否尝试在退出后附加到它,暂停线程并查看什么仍然处于活动状态?不确定应用程序是否退出语义,但前台线程通常不希望退出,除非显式endedwhat aboutProcess.GetCurrentPr
public async Task Run(CancellationTokenSource cancellationTokenSource)
{
// ...
while (Running) {
if (cancellationTokenSource.IsCancellationRequested) return;
// ....
}
// ....
using (var reader = new WaveFileReader(tempFile))
{
reader.Position = 0;
await reader.CopyToAsync(fileWriter,81920, cancellationTokenSource.Token);
}
}