Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Graceful detruction of object containing thread.

Posted on 2011-02-11
6
Medium Priority
?
320 Views
Last Modified: 2012-05-11
I have an arraylist MyList of MyMonitored objects. Within the MyMonitored class is a running thread object.

What is the best practice to remove the MyMonitored instance from MyList? Can I just remove the MyMonitored instance from MyList and let GC handle it, or do need to ensure the thread running within the object has stopped first?  If so, can I just to this within the MyMonitored class's destructor?
0
Comment
Question by:brenlex
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
6 Comments
 

Author Comment

by:brenlex
ID: 34871575
Thanks, but not really.  I do not need the thread to invoke any activity outside of its own scope of the instance in which it is run.  I just need to remove the instance of MyMonitored from MyList and be confident that the MyMonitored object destroys itself properly (i.e. the threaded process running within the MyMonitored object has stopped first).

I could expose a public bool var 'HasStopped' within the MyMonitored class and run a while loop before I remove it from MyMonitored list, but I am sure there is a better way...
0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 1000 total points
ID: 34872099
If you no longer need the object, or the thread within to run, then you should STOP the thread before removing it.  This way you have more available resources as a whole.  Switching between running threads (while invisible to you) is a burden on the system.

*If you have set the IsBackground() property of the thread to true then it will be killed automatically when the app closes.

Is the nature of the thread such that you can set a flag in the object to cause the thread to exit gracefully?
If not, can you set it up with a ManualResetEvent to break its waitstate and exit?
As a last resort you can call Abort() on the thread to kill it forcefully...
0
Understanding Linux Permissions

Linux for beginners: How to view the permissions associated with files and directories and also how you can change them.

 
LVL 33

Assisted Solution

by:Todd Gerbert
Todd Gerbert earned 1000 total points
ID: 34872226
As Idle_Mind already pointed out, I wouldn't leave un-needed threads lingering around, waiting for the GC to get to them.  I would implement IDisposable on your MyMonitored object, and have MyMonitored terminate the thread.

As opposed to using a List<MyMonitored> I would create my own collection (inherit from Collection<T>, for example) which itself also implements IDisposable.  This way, you can override the remove method and have it call Dispose() on the MyMonitored object in the collection, in addition to removing it from the list.

MSDN says that a reference to a thread isn't needed, that it'll just keep running through to completion - so I'm not 100% sure whether or not you should clean up the thread when the GC runs the destructor, or just when the Dispose() method is explicitly called (I'm leaning towards the latter).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.ObjectModel;

class Program
{
	static void Main(string[] args)
	{
		MyList list = new MyList();

		MyMonitoredObject obj = new MyMonitoredObject();
		list.Add(obj);

		list.Remove(obj);
	}
}

public class MyList : Collection<MyMonitoredObject>, IDisposable
{
	private bool disposed = false;

	~MyList()
	{
		Dispose(false);
	}

	public void Dispose()
	{
		Dispose(true);
		GC.SuppressFinalize(this);
	}

	private void Dispose(bool disposing)
	{
		if (!disposed && disposing)
		{
			disposed = true;

			foreach (MyMonitoredObject item in Items)
				item.Dispose();

			Items.Clear();
		}
	}

	protected override void RemoveItem(int index)
	{
		Items[index].Dispose();
		base.RemoveItem(index);
	}
}

public class MyMonitoredObject : IDisposable
{
	private bool disposed = false;
	
	private Thread worker;
	private ManualResetEvent runWorkerFlag;

	public MyMonitoredObject()
	{
		runWorkerFlag = new ManualResetEvent(true);
		worker = new Thread(ThreadProc);
		worker.IsBackground = true;
		worker.Start();
	}

	~MyMonitoredObject()
	{
		// Destructor will be called if GC cleans us up
		Dispose(false);
	}

	public void Dispose()
	{
		// Dispose has been explicitly called
		Dispose(true);
		GC.SuppressFinalize(this); // Tell GC no need to run destructor on this object
	}

	private void Dispose(bool disposing)
	{
		if (!disposed)
		{
			disposed = true;

			// If Dispose has been explicitly called clean up the thread
			// and other managed resources
			if (disposed)
			{
				// Tell thread to exit
				runWorkerFlag.Reset();
			}
			else
			{
				// If Dispose has been called as a result of garbage collection
				// there's a chance the GC might have already cleaned up any 
				// managed objects, including our runWorkerFlag, so the only thing to
				// do here is clean up UN-managed resources - like handles opened
				// with calls to Windows APIs
			}
		}
	}

	private void ThreadProc()
	{
		// Run loop so long as runWorkerFlag is signaled,
		// when runWorkerFlag is nonsignaled exit loop and
		// let thread finish
		while (runWorkerFlag.WaitOne(0))
		{
			// Do some work here
			Console.WriteLine("Worker thread with ID {0} running.", Thread.CurrentThread.ManagedThreadId);
			Thread.Sleep(3000);
		}
	}
}

Open in new window

0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34872258
I made a typo, line 92 should be if (disposing), also (if you use a Collection<T>) make sure you override ClearItems() as well.
0
 

Author Comment

by:brenlex
ID: 34929607
Thanks tgerbert, but my MyList object is already an instance of an existing threadsafe class which encapsulates an arraylist.  I have gone for the option of using ManualResetEvent to stop the thread, which in turn reports via callback when gracefully stopped, allowing me to destroy MyMonitord instance.

I shall try out your recommended method in the near future (for a similar project) though.  Hence point split.

Many thanks.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…

721 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question