Here’s an interesting library writer’s dilemma. In my library (in my case EasyNetQ) I’m assigning thread local resources. So when a client creates a new thread and then calls certain methods on my library new resources get created. In the case of EasyNetQ a new channel to the RabbitMQ server is created when the client calls ‘Publish’ on a new thread. I want to be able to detect when the client thread exits so that I can clean up the resources (channels).
The only way of doing this I’ve come up with is to create a new ‘watcher’ thread that simply blocks on a Join call to the client thread. Here a simple demonstration:
First my ‘library’. It grabs the client thread and then creates a new thread which blocks on ‘Join’:
public class Library
{
public void StartSomething()
{
Console.WriteLine("Library says: StartSomething called");
var clientThread = Thread.CurrentThread;
var exitMonitorThread = new Thread(() =>
{
clientThread.Join();
Console.WriteLine("Libaray says: Client thread existed");
});
exitMonitorThread.Start();
}
}
Here’s a client that uses my library. It creates a new thread and then calls my library’s StartSomething method:
public class Client
{
private readonly Library library;
public Client(Library library)
{
this.library = library;
}
public void DoWorkInAThread()
{
var thread = new Thread(() =>
{
library.StartSomething();
Thread.Sleep(10);
Console.WriteLine("Client thread says: I'm done");
});
thread.Start();
}
}
When I run the client like this:
var client = new Client(new Library());
client.DoWorkInAThread();
// give the client thread time to complete
Thread.Sleep(100);
I get this output:
Library says: StartSomething called
Client thread says: I'm done
Libaray says: Client thread existed
The thing is, I really don’t like the idea of all these blocked watcher threads hanging around. Is there a better way of doing this?
Thought: If a threadlocal resource implements IDisposable would Dispose() be called when the thread finishes?
ReplyDeleteHi Karl, No, it wouldn't. Something has to call Dispose.
ReplyDeleteI've copied this onto StackOverflow where there's quite a good discussion going on: http://stackoverflow.com/questions/10432494/how-do-i-detect-when-a-client-thread-exits
ReplyDeleteGood point.
ReplyDeleteI answered your questing over at stackoverflow: http://stackoverflow.com/a/10435718/61061
ReplyDeleteIn short, the combination of thread-static resource that has a finalizer can be used to observe the death of threads.
I hope it helps. I think it's more elegant than your extra waiting thread.
:) Just came back to suggest adding a destructor but Omer beat me to it. Too slow...
ReplyDeleteWhat in the world are you doing putting an item like that on thread local storage?
ReplyDelete