gpt4 book ai didi

c# - 如何删除应用程序中启动的所有线程?

转载 作者:行者123 更新时间:2023-11-30 15:35:29 26 4
gpt4 key购买 nike

我有一个 WPF 应用程序,它使用许多在自己的线程中运行的第三方 DLL。

其中一些 DLL 具有方法 STOP()

我在每个 SomeObject.Stop() 方法之后使用 Thread.Sleep(1000)...

无论如何,当我终止应用程序时,一些线程仍在内存中。

知道如何解决这个问题吗?

最佳答案

所以基本上你面临的是第 3 方库的问题,它在应该清理的时候没有很好地清理,最重要的是,它启动了一堆前台线程,即使你想要它终止,你的应用程序也能保持运行.

例子

举个例子,像这样的一个应用

private static void Main(string[] args)
{

var t = new Thread(() =>
{
while (true)
{
}
}) {Name = "test"};

t.Start();

Console.WriteLine("Exited");
}

因为 t 是一个前台线程,所以会永远存在。

让我们用 Process Explorer 仔细检查一下。这是我们的演示应用程序的更新版本,我们可以调用它并获取 native 线程 ID。

internal class Program
{
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);


[DllImport("kernel32.dll")]
static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);

[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();

private static void Main(string[] args)
{

var t = new Thread(() =>
{
Console.WriteLine(GetCurrentThreadId());
while (true)
{
}
}) {Name = "test"};

t.Start();

Console.WriteLine("Thread Id " + t.ManagedThreadId);
Console.WriteLine("Exited");

}
}

给我 native 线程 ID。在进程资源管理器中,我现在可以看到:

spinning thread

很明显线程 8228 由于我的 while 循环而疯狂旋转,即使 main 已经退出

总的来说,用户 Rob Hardy 是对的。如果您控制您的线程,您应该始终跟踪事情并自己管理它们,但我认为您在这里陷入困境,因为您无权访问线程句柄。

选项 1(但请不要)

你可以试试kill everything (但无论如何,当我尝试时,这对我来说并没有真正起作用),但我真的不会这样做,因为这样做似乎非常危险。只是为了复制其他帖子中的信息,示例是这样说的:

internal class Program
{
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);


[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);

private static void Main(string[] args)
{

var t = new Thread(() =>
{
while (true)
{
}
}) {Name = "test"};

t.Start();

Console.WriteLine("Exited");

Thread.Sleep(TimeSpan.FromSeconds(2));

foreach (ProcessThread pt in Process.GetCurrentProcess().Threads)
{
IntPtr ptrThread = OpenThread(1, false, (uint)pt.Id);
if (AppDomain.GetCurrentThreadId() != pt.Id)
{
try
{
TerminateThread(ptrThread, 1);
Console.Out.Write(". Thread killed.\n");
}
catch (Exception e)
{
Console.Out.WriteLine(e.ToString());
}
}
else
Console.Out.Write(". Not killing... It's the current thread!\n");
}
}
}

但同样,这并没有阻止我的进程。也许 .net 正在等待线程的正确退出,而不仅仅是强制 native 退出?我不知道。我只是想表明,如果您真的想要(但请不要这样做),您可以从技术上(根据链接)杀死来自 ProcessThread 的线程

选项 2

一个更合理的选择是在所有清理之后添加一个带有代码的显式 Exit 调用(退出代码 0 通常表示干净退出)

private static void Main(string[] args)
{

var t = new Thread(() =>
{
while (true)
{
}
}) {Name = "test"};

t.Start();

Console.WriteLine("Exited");

Environment.Exit(0);
}

这对我有用。

选项3

第三种选择,如果可以的话,就是修复库并让它创建后台线程或让它正确清理。这将是最好的选择,因为您不会因为不清理第 3 方项目而留下任何潜在的可破坏的副作用。不过,我假设您没有这样做,因为该库是闭源的。

关于c# - 如何删除应用程序中启动的所有线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14853774/

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