wpf 如何删除应用程序中启动的所有线程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14853774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to delete all threads started within an application?
提问by Developer
I have an WPF application that uses many third-party DLLs which are working in their own threads.
我有一个 WPF 应用程序,它使用许多在自己的线程中工作的第三方 DLL。
Some of those DLLs have method STOP().
其中一些 DLL 具有方法STOP().
I am using Thread.Sleep(1000)after each SomeObject.Stop()method...
我Thread.Sleep(1000)在每种SomeObject.Stop()方法后使用...
Anyway when I terminate application some of the threads are still in memory.
无论如何,当我终止应用程序时,一些线程仍在内存中。
Any clue how to resolve this problem?
任何线索如何解决这个问题?
回答by devshorts
So basically you're facing an issue with a 3rd party library that doesn't nicely clean up when it should, and on top of that its spun up a bunch of foreground threads keeping your application running even when you want it terminated.
所以基本上你面临的问题是第 3 方库在它应该清理的时候没有很好地清理,最重要的是它启动了一堆前台线程,即使你想要它终止,它也能保持你的应用程序运行。
Example
例子
As an example, an application like this
例如,这样的应用程序
private static void Main(string[] args)
{
var t = new Thread(() =>
{
while (true)
{
}
}) {Name = "test"};
t.Start();
Console.WriteLine("Exited");
}
Will sit forever since tis a foreground thread.
因为t是前台线程,所以将永远坐着。
Let's just double check with process explorer. Here's an updated version of our demo app that we can pinvoke and get the native thread id.
让我们仔细检查流程资源管理器。这是我们的演示应用程序的更新版本,我们可以调用它并获取本机线程 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");
}
}
Gives me the native thread id. In process explorer I can see now:
给我本机线程 ID。在进程浏览器中,我现在可以看到:


Pretty clear that thread 8228 is spinning wildly because of my while loop, even though main has already exited
很明显,由于我的 while 循环,线程 8228 正在疯狂旋转,即使 main 已经退出
In general, User Rob Hardy is right. If you control your threads you should always keep track of things and manage them yourself, but I think you're in a pickle here since you don't have access to the thread handles.
总的来说,用户 Rob Hardy 是对的。如果您控制您的线程,您应该始终跟踪事物并自己管理它们,但我认为您在这里陷入困境,因为您无权访问线程句柄。
Option 1 (but please don't)
选项1(但请不要)
You can try and kill everything(but that didn't really work for me when I tried it anyways), but I really wouldn't do this since it seems incredibly dangerous to do. Just to copy the information from the other post the example said this:
你可以尝试杀死所有东西(但是当我尝试它时这对我来说并没有真正起作用),但我真的不会这样做,因为这样做似乎非常危险。只是为了从另一篇文章中复制信息,该示例是这样说的:
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");
}
}
}
But again, that didn't stop the process for me. Maybe .net is waiting for proper exiting of the threads and not just forceful native exits? I don't know. I'm just showing that you can technically (according to the link) can kill threads from ProcessThread, if you REALLY wanted to (but please don't)
但同样,这并没有阻止我的过程。也许 .net 正在等待线程的正确退出,而不仅仅是强制本机退出?我不知道。我只是表明你可以在技术上(根据链接)可以杀死来自 的线程ProcessThread,如果你真的想要(但请不要)
Option 2
选项 2
A more reasonable option is to add an explicit Exitcall with a code after all your cleanup (exit code 0 is customary to indicate a clean exit)
更合理的选择是Exit在所有清理之后添加一个带有代码的显式调用(退出代码 0 通常表示干净退出)
private static void Main(string[] args)
{
var t = new Thread(() =>
{
while (true)
{
}
}) {Name = "test"};
t.Start();
Console.WriteLine("Exited");
Environment.Exit(0);
}
This worked for me.
这对我有用。
Option 3
选项 3
The third option, if you can, is to just fix the library and have it either create background threads or let it clean up properly. This would be the best option since you won't be leaving any potential corruptible side effects open by not cleaning up the 3rd party items. Though, I'm assuming you aren't doing this because the library is closed source.
如果可以,第三个选项是修复库并让它创建后台线程或让它正确清理。这将是最好的选择,因为您不会因为不清理第 3 方项目而留下任何潜在的易腐化副作用。不过,我假设您没有这样做,因为该库是封闭源代码。
回答by Rob Hardy
Keep track of your threads by adding them to a collection, or using the ThreadPool
通过将它们添加到集合来跟踪您的线程,或使用 ThreadPool
In each thread make sure that you handle the ThreadAbortException
在每个线程中确保您处理 ThreadAbortException
At the termination point at the end of your Main(), go through your collection of Threads and call Abort()on each one.
在 末尾的终止点Main(),浏览您的线程集合并调用Abort()每个线程。

