How can I remove all threads running in the application?

I have a WPF application that uses a lot of 3rd party DLLs that run in their threads.

Some of these DLLs have a method STOP()

.

I use Thread.Sleep(1000)

after each method SomeObject.Stop()

...

Anyway, when I terminate the application, some of the threads are still in memory.

Can this problem be solved?

+3


source to share


2 answers


So basically you are running into a problem with a third party library that doesn't clean it up very well when needed, and furthermore, it bundles many foreground threads, keeping your application alive even when you want it to terminate ...

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");
}

      

It will sit forever, as it t

is a forward stream.

Let's just double check with process explorer. Here's an updated version of our demo application that we can dump and get the id of our own thread.

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 my own thread id. In the process explorer I can see now:

spinning thread

It's pretty clear that thread 8228 is spinning wildly due to my while loop, even though main has already exited

In general, user Rob Hardy is right. If you are in control of your flows, you should always keep track of and manage things yourself, but I think you are in the brine since you have no access to flow handles.



Option 1 (but please don't)

You can try and kill everything (but it didn't actually work for me when I tried it), but I really don't, because it seems incredibly dangerous. Just to copy information from another post, this example said the following:

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 the current thread!\n");
        }
    }
}

      

But then again , that didn't stop the process for me . Maybe .net is waiting for proper thread exits and not just strong native exits? I dont know. I am just showing that you can technically (from the link) can kill threads from ProcessThread

if you REALLY wanted to (but please don't)

Option 2

A smarter option is to add an explicit call Exit

with code after all the cleanup (exit code 0 usually indicates a clean exit)

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

A third option, if possible, is to simply fix the library and either create a background thread or let it clean up properly. This would be the best option as you won't leave any potential damaged side effects without cleaning up the third-party items. Although, I am assuming that you do not, because the library is closed.

+4


source


Track your streams by adding them to a collection or using ThreadPool

In each thread, make sure you process ThreadAbortException



At the endpoint at the end of yours, Main()

browse through your collection of threads and call Abort()

on each one.

0


source







All Articles