我有一个WPF应用程序,它使用许多第三方DLL,它们在自己的线程中工作。
其中一些DLL有方法STOP()
。
我在每个Thread.Sleep(1000)
方法后使用SomeObject.Stop()
...
无论如何,当我终止应用程序时,一些线程仍在内存中。
有任何线索如何解决这个问题?
答案 0 :(得分:4)
所以基本上你面临的问题是第三方库在它应该的时候不能很好地清理,并且除此之外它还会产生一堆前景线程,即使你希望它终止也能保持你的应用程序运行
例如,像这样的应用程序
private static void Main(string[] args)
{
var t = new Thread(() =>
{
while (true)
{
}
}) {Name = "test"};
t.Start();
Console.WriteLine("Exited");
}
因为t
是前景线程所以会永远坐着。
让我们仔细检查进程资源管理器。这是我们的演示应用程序的更新版本,我们可以调整并获取本机线程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");
}
}
给我本机线程ID。在进程资源管理器中,我现在可以看到:
很明显,由于我的while循环,线程8228正在疯狂地旋转,即使main已经退出
一般来说,用户Rob Hardy是对的。如果你控制你的线程,你应该总是跟踪事情并自己管理它们,但我认为你在这里是一个泡菜,因为你没有访问线程句柄。
你可以尝试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正在等待正确退出线程而不仅仅是强有力的本机退出?我不知道。我只是表明你可以在技术上(根据链接)杀死来自ProcessThread
的线程,如果你真的想(但请不要)
更合理的选择是在所有清理之后添加一个带代码的显式Exit
调用(通常退出代码0表示一个干净的退出)
private static void Main(string[] args)
{
var t = new Thread(() =>
{
while (true)
{
}
}) {Name = "test"};
t.Start();
Console.WriteLine("Exited");
Environment.Exit(0);
}
这对我有用。
如果可以,第三个选项是修复库并让它创建后台线程或让它正确清理。这将是最好的选择,因为你不会通过不清理第三方物品而留下任何潜在的腐败副作用。虽然,我假设你没有这样做,因为图书馆是闭源的。
答案 1 :(得分:0)
通过将线程添加到集合或使用ThreadPool
在每个帖子中,请确保您处理ThreadAbortException
在Main()
末尾的终止点,浏览您的主题广告集并在每个主题上致电Abort()
。