2

I'm developing a project on Visual Studio 2015 using C# and WPF. Sometimes I quit my running project with my close command, and sometimes with the stop debug button. The problem is that after a few tests, my PC starts to warm and the fans make noise. I have to quit Visual Studio to calm the machine.

So I have questions :

  • How to see the threads not ended after a test ?
  • When I know them, how to properly end them ? (actually I Dispose some threads when WindowClosing)
  • How make sure that thread will properly ends when I use the stop debug button ?

Thank you

EDIT:

There is the screenshot of task manager. When I start application the CPU rise from 5% to 15% (or event 25%). RAM rise from 4GO to 4.5. When I stop application, CPU goes to 45% for a few seconds and go back to 5% but RAM goes to 4.70GO and doesn't go back down.

task manager

EDIT2:

I founded this kind of thread on my application:

private bool isClosing = false;
public void Start()
{
    isClosing = false;
    ThreadPool.QueueUserWorkItem(new WaitCallback(doWorkThread));
}

public void Stop()
{
    isClosing = true;
}

private AutoResetEvent endPoolStateButton = new AutoResetEvent(false);
private void doWorkThread(object sender)
{
    Action action = new Action(() => doWork());
    while (!isClosing)
    {
        Thread.Sleep(100);
        this.Dispatcher.BeginInvoke(action, System.Windows.Threading.DispatcherPriority.Background);
    }
    endPoolStateButton.Set();
}

private void doWork()
{
    /* Job performed */
}

I wonder if there is a really good way to use thread ? If application close without setting isClosing = true the while never stop. And the thread is never really aborted ? Do you think that this kind of thread can cause all the troubles I have ?

A.Pissicat
  • 3,023
  • 4
  • 38
  • 93
  • Look at the Task Manager and check out what's happening. If the app is still running after you "close" it. If it takes large amount of RAM. If the CPU works at 100%... – Martin Heralecký Jul 22 '16 at 08:02
  • How are you starting the new threads and when and how are they terminated? And what does "dispose some threads" mean? Threads aren't disposable. And you need to let all foreground threads finish before the application exits, not just "some". – Luaan Jul 22 '16 at 08:23
  • I'm not the only developer on this application, some features has been developed before I work on it. So I don't know haw all the thread are started/ended, that's why I'm asking the question. For example I use a background woker and I abort it (not Dispose, sorry for the mistake) [created from there](http://stackoverflow.com/questions/800767/how-to-kill-background-worker-completely) – A.Pissicat Jul 22 '16 at 08:35
  • @A.Pissicat, you can use my tool https://github.com/REASY/ProcInfo4Net to get info about the state of threads – Artavazd Balayan Jul 22 '16 at 08:40
  • http://stackoverflow.com/questions/5002279/killing-all-threads-that-opened-by-application – Felix D. Jul 22 '16 at 08:49
  • http://stackoverflow.com/a/2314896/4610605 – Felix D. Jul 22 '16 at 08:49
  • @A.Pissicat, private bool isClosing = false it must be [volatile](https://msdn.microsoft.com/en-us//library/x13ttww7.aspx) to ensure that the most up-to-date value is present in the field at all times. – Artavazd Balayan Jul 22 '16 at 10:14

2 Answers2

0

Here is my solution how to stop thread in elegant way. Hope the code is clear. I use CancellationToken to cancel operations in thread and ManualResetEvent to wait for thread cancellation:

namespace ElegantThreadWork
{
    using System;
    using System.Threading;
    using System.Diagnostics;

    class ThreadObject
    {
        public CancellationToken CancellationToken { get; private set; }
        public ManualResetEvent WaitHandle { get; private set; }

        public ThreadObject(CancellationToken ct, ManualResetEvent wh)
        {
            CancellationToken = ct;
            WaitHandle = wh;
        }
    }
    public class Program
    {
        static void DoWork(CancellationToken ct)
        {
            Console.WriteLine("Thread[{0}] started", Thread.CurrentThread.ManagedThreadId);
            int i = 0;
            // Check for cancellation on each iteration
            while (!ct.IsCancellationRequested)
            {
                // Do something
                Console.WriteLine("Thread[{0}]: {1}", Thread.CurrentThread.ManagedThreadId, i);
                // Wait on CancellationToken. If cancel be called, WaitOne() will immediatly return control!
                // You can see it by elapsed time
                ct.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
                i++;
            }
            Console.WriteLine("Thread[{0}] has been cancelled", Thread.CurrentThread.ManagedThreadId);
        }
        static void ThreadProc(object state)
        {
            ThreadObject to = (ThreadObject)state;
            try
            {
                DoWork(to.CancellationToken);
            }
            finally
            {
                to.WaitHandle.Set();
            }
        }
        public static void Main(string[] args)
        {
            TimeSpan MAX_THREAD_EXITING_TIMEOUT = TimeSpan.FromSeconds(5);

            // Use for elegant thread exiting
            ManualResetEvent isThreadExitedEvent = new ManualResetEvent(false);
            CancellationTokenSource cts = new CancellationTokenSource();
            ThreadObject threadObj = new ThreadObject(cts.Token, isThreadExitedEvent);

            // Create thread
            Thread thread = new Thread(ThreadProc, 0);
            thread.Start(threadObj);

            Console.WriteLine("Just do something in main thread");

            Console.WriteLine("Bla.");
            Thread.Sleep(1000);

            Console.WriteLine("Bla..");
            Thread.Sleep(1000);

            Console.WriteLine("Bla...");
            Thread.Sleep(1000);

            Console.WriteLine("Thread cancelattion...");
            Stopwatch sw = Stopwatch.StartNew();
            // Cancel thread
            cts.Cancel();

            // Wait for thread exiting
            var isOk = isThreadExitedEvent.WaitOne(MAX_THREAD_EXITING_TIMEOUT);
            sw.Stop();
            Console.WriteLine("Waiting {0} for thread exiting. Wait result: {1}. Cancelled in {2}", MAX_THREAD_EXITING_TIMEOUT, isOk, sw.Elapsed);

            // If we couldn't stop thread in elegant way, just abort it
            if (!isOk)
                thread.Abort();
        }
    }
}
Artavazd Balayan
  • 2,353
  • 1
  • 16
  • 25
  • I'll try this solution, but before I need to list all the threads created on this application and the list is long... Most of the thread is type `while (!close){...}` and they are never aborted. I have a hard job to clean them all. – A.Pissicat Jul 22 '16 at 09:59
  • if you control these threads creation, use [Thread.IsBackground](https://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground(v=vs.110).aspx). Background threads are identical to foreground threads, except that background threads **do not prevent a process from terminating**. – Artavazd Balayan Jul 22 '16 at 10:11
-1

Maybe you can try to observe the behaviour of the process and the threads with the tool "Process Hacker". With this tool you get more detailed informations about the thread and you also can detect deamon threads.

Another way could be: Try to get all child threads of the main process and do something like

Thread t1; // specific child thread 
t1.join();