ThreadPool in C# - c#

I have two questions:
Is there a way to insert a ThreadPool functoin that dosen't gets
object as parameter(to insert a function to threadPool it need to be function that return void and ged one parameter -object) e.g i want to insert this function: double foo(int a,double b,string c)?
Is there a way to wait to thread in the pool (like join)?

For the first part, the easiest approach is probably:
Assuming a method per your description:
public double foo(int a, double b, string c)
{
...
}
You can queue this on the thread pool with:
ThreadPool.QueueUserWorkItem(o => foo(a, b, c));
For the second part, while you can't wait on a ThreadPool thread, you can call methods asynchronously on the thread pool, and wait on their completion (which seems to be what you're looking for).
Again, assuming the Foo method is defined as above.
Define a Delegate for Foo:
private delegate double FooDelegate(int a, double b, string c);
Then to call Foo asynchronously using the BeginInvoke/EndInvoke methods of the FooDelegate:
// Create a delegate to Foo
FooDelegate fooDelegate = Foo;
// Start executing Foo asynchronously with arguments a, b and c.
var asyncResult = fooDelegate.BeginInvoke(a, b, c, null, null);
// You can then wait on the completion of Foo using the AsyncWaitHandle property of asyncResult
if (!asyncResult.CompletedSynchronously)
{
// Wait until Foo completes
asyncResult.AsyncWaitHandle.WaitOne();
}
// Finally, the return value can be retrieved using:
var result = fooDelegate.EndInvoke(asyncResult);
To address the question raised in the comments. If you want to execute multiple function calls in parallel and wait for them all to return before continuing, you could use:
// Create a delegate to Foo
FooDelegate fooDelegate = Foo;
var asyncResults = new List<IAsyncResult>();
// Start multiple calls to Foo() in parallel. The loop can be adjusted as required (while, for, foreach).
while (...)
{
// Start executing Foo asynchronously with arguments a, b and c.
// Collect the async results in a list for later
asyncResults.Add(fooDelegate.BeginInvoke(a, b, c, null, null));
}
// List to collect the result of each invocation
var results = new List<double>();
// Wait for completion of all of the asynchronous invocations
foreach (var asyncResult in asyncResults)
{
if (!asyncResult.CompletedSynchronously)
{
asyncResult.AsyncWaitHandle.WaitOne();
}
// Collect the result of the invocation (results will appear in the list in the same order that the invocation was begun above.
results.Add(fooDelegate.EndInvoke(asyncResult));
}
// At this point, all of the asynchronous invocations have returned, and the result of each invocation is stored in the results list.

The answer to both of these questions is no, not with the native ThreadPool, although you can achieve the same result if you package your input args into the state object and write mechanisms to provide wait functionality and get the result of the work item method.
http://smartthreadpool.codeplex.com/ does everything you want;
public static void Main(string[] args)
{
var threadPool = new SmartThreadPool();
IWorkItemResult<int> workItem=null;
SmartThreadPool.WaitAll(new IWaitableResult[ ]{workItem = threadPool.QueueWorkItem(new Amib.Threading.Func<int, int, int>(Add), 1, 2)});
Console.WriteLine(workItem.Result);
Console.ReadLine();
}
public static int Add(int a, int b)
{
return a+b;
}

Re your first question, create a new method of the correct signature (returns void, one object parameter) that calls foo. If you need to pass in specific arguments to foo then create a class or struct or use a Tuple<int, double, double> and cast it to object to pass it into ThreadMethod, then back to Tuple to get the arguments to foo.
void ThreadMethod(object obj)
{
var args = (Tuple<int, double, double>)obj;
foo(args.Item1, args.Item2, args.Item3);
}
Re. 2nd question, you'd have to create the thread yourself so you can keep a Thread object to join with.

For the first question
I think you can create a new class as a parameter
for exsample
interface IAction
{
void Do();
}
class SubClass : IAction
{
object _param;
public SubClass(object o)
{
_param = o;
}
public void Do()
{
// your current code in here
}
}
SubClass sc = new SubClass("paramter");
System.Threading.ThreadPool.QueueUserWorkItem(action => {
var dosomething = action as IAction;
dosomething.Do();
}, sc);
So , you donnt need to change any code in your current function ...

The classic way of doing it is below, however as Iridium has shown there's more compact ways of doing it now. If you're using .NET 4 you can use the parallel APIs or more precisely Tasks to make it even easier.
public class MyWorker
{
private int _a;
private double _b;
private string _c;
Action complete
public MyWorker(int a,double b,string c)
{
_a = a;
_b = b;
_c = c;
}
public void Run(object state)
{
double result = Foo();
}
private double Foo()
{
// Do something with _a, _b, _c
}
}
MyWorker worker = new MyWorker(1,1,"");
ThreadPool.QueueUserWorkItem(worker.Run);
There's an equivalent example on the MSDN page.
In terms of being notified when a thread in a threadpool is completed, you can use a WaitHandle
inside the object. Presumably you don't want to block until the thread is completed, in which
case an event, Action or Func in the MyWorker class would be another solution.
I'd recommend reading Joe Albahari's free ebook on Threading as covers the subjects in a lot more detail.

Related

Running Tasks generically

In my project I heavily make use of TPL, and I decide to design a generic way of producing tasks, instead of calling new Task(Action);, new Task(Action<object>, object); or Task.Factory.StartNew(Action) etc. explicitly.
I will have a function like
void SpawnTask<A,B>( Action<A,B> action, A a, B b) { ... }
void SpawnTask<A,B,C>( Action<A,B,C> action, A a, B b, C c) { ... }
for creating and starting tasks.
Also I need to run a mandatory method after each task completed. Thus I have to wrap the actual method I want to run in another method like
void RuncTask(Action action)
{
action();
MandatoryMethod();
}
So far I come up with two different approaches.
First, using anonymous delegates:
void SpawnTask<A,B>(Action<A,B> action, A a, B b)
{
A dummyA = a; // To localize the parameters.
B dummyB = b;
var methodDelegate = delegate { action(dummyA,dummyB); };
var taskDelegate = delegate { RunTask(methodDelegate); };
Task.Factory.StartNew( taskDelegate );
}
void RuncTask(Action action)
{
action();
MandatoryMethod();
}
Second, using tuple:
void SpawnTask<A,B>(Action<A,B> action, A a, B b)
{
Tuple<Action<A,B>, A, B> tpl = Tuple.Create(action, a, b);
Action<object> act = RunTask<A,B>;
Task.Factory.StartNew( act, tpl );
}
void RuncTask<A,B>(object obj)
{
var tpl = (Tuple<Action<A, B>, A, B>)param;
tpl.Item1(tpl.Item2,tpl.Item3);
MandatoryMethod();
}
I like the first one because, it is simpler. The second has casting, requires other generic RunTask methods to be implemented for different number of parameters. But I do not know if creating too much anonymous delegates can cause side effects.
Which one do you prefer? Why? Or what other solutions do you have?
Well, you can always create an extension method on Action<TA,TB> ... and you should use continuations rather than wrapped method calls to implement the behavior of always performing another action when the task completes:
public static class TaskExtensions
{
public static void RunTask<TA,TB>( Action<TA,TB> action, TA a, TB b )
{
Task newTask = new Task( () => action(a,b) );
newTask.ContinueWith( MandatoryMethod );
newTask.Start();
}
// if you need to support other signature (more parameters) you would need to
// create additional overloads of RunTask with more generic parameters...
public static void RunTask( Action action );
public static void RunTask<TA>( Action<TA> action, TA a );
// etc ...
private static void MandatoryMethod( Task t ) { /* your continuation logic */ }
}
Now you can use this code as follows:
public void SomeMethod( int x, int y ) { ... }
// later...
Action<int,int> myAction = SomeMethod;
myAction.RunTask( 1, 2 );
Note that in the above implementation the continuation method (MandatoryMethod) will be executed asynchronously. If you desire synchronous execution (as is implemented in your example), you can use the overload of ContinueWith that takes a TaskContinuationOptions and pass in TaskContinuationOptions.ExecuteSynchronously.
Frankly, I mot quite sure what you are trying to accomplish with that. What advantage over directly using Task constructor or Task.Factory are you hoping to achieve?
As for a "mandatory method" that needs to execute after task finishes, look at continuations (e.g. Task.ContinueWith).

How to pass parameters to ThreadStart method in Thread?

How to pass parameters to Thread.ThreadStart() method in C#?
Suppose I have method called 'download'
public void download(string filename)
{
// download code
}
Now I have created one thread in the main method:
Thread thread = new Thread(new ThreadStart(download(filename));
error method type expected.
How can I pass parameters to ThreadStart with target method with parameters?
The simplest is just
string filename = ...
Thread thread = new Thread(() => download(filename));
thread.Start();
The advantage(s) of this (over ParameterizedThreadStart) is that you can pass multiple parameters, and you get compile-time checking without needing to cast from object all the time.
Look at this example:
public void RunWorker()
{
Thread newThread = new Thread(WorkerMethod);
newThread.Start(new Parameter());
}
public void WorkerMethod(object parameterObj)
{
var parameter = (Parameter)parameterObj;
// do your job!
}
You are first creating a thread by passing delegate to worker method and then starts it with a Thread.Start method which takes your object as parameter.
So in your case you should use it like this:
Thread thread = new Thread(download);
thread.Start(filename);
But your 'download' method still needs to take object, not string as a parameter. You can cast it to string in your method body.
You want to use the ParameterizedThreadStart delegate for thread methods that take parameters. (Or none at all actually, and let the Thread constructor infer.)
Example usage:
var thread = new Thread(new ParameterizedThreadStart(download));
//var thread = new Thread(download); // equivalent
thread.Start(filename)
You could also delegate like so...
ThreadStart ts = delegate
{
bool moreWork = DoWork("param1", "param2", "param3");
if (moreWork)
{
DoMoreWork("param1", "param2");
}
};
new Thread(ts).Start();
In Additional
Thread thread = new Thread(delegate() { download(i); });
thread.Start();
I would recommend you to have another class called File.
public class File
{
private string filename;
public File(string filename)
{
this.filename= filename;
}
public void download()
{
// download code using filename
}
}
And in your thread creation code, you instantiate a new file:
string filename = "my_file_name";
myFile = new File(filename);
ThreadStart threadDelegate = new ThreadStart(myFile.download);
Thread newThread = new Thread(threadDelegate);
You can encapsulate the thread function(download) and the needed parameter(s)(filename) in a class and use the ThreadStart delegate to execute the thread function.
public class Download
{
string _filename;
Download(string filename)
{
_filename = filename;
}
public void download(string filename)
{
//download code
}
}
Download = new Download(filename);
Thread thread = new Thread(new ThreadStart(Download.download);
How about this: (or is it ok to use like this?)
var test = "Hello";
new Thread(new ThreadStart(() =>
{
try
{
//Staff to do
Console.WriteLine(test);
}
catch (Exception ex)
{
throw;
}
})).Start();
According to your question...
How to pass parameters to Thread.ThreadStart() method in C#?
...and the error you encountered, you would have to correct your code from
Thread thread = new Thread(new ThreadStart(download(filename));
to
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
However, the question is more complex as it seems at first.
The Thread class currently (4.7.2) provides several constructors and a Start method with overloads.
These relevant constructors for this question are:
public Thread(ThreadStart start);
and
public Thread(ParameterizedThreadStart start);
which either take a ThreadStart delegate or a ParameterizedThreadStart delegate.
The corresponding delegates look like this:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
So as can be seen, the correct constructor to use seems to be the one taking a ParameterizedThreadStart delegate so that some method conform to the specified signature of the delegate can be started by the thread.
A simple example for instanciating the Thread class would be
Thread thread = new Thread(new ParameterizedThreadStart(Work));
or just
Thread thread = new Thread(Work);
The signature of the corresponding method (called Work in this example) looks like this:
private void Work(object data)
{
...
}
What is left is to start the thread. This is done by using either
public void Start();
or
public void Start(object parameter);
While Start() would start the thread and pass null as data to the method, Start(...) can be used to pass anything into the Work method of the thread.
There is however one big problem with this approach:
Everything passed into the Work method is cast into an object. That means within the Work method it has to be cast to the original type again like in the following example:
public static void Main(string[] args)
{
Thread thread = new Thread(Work);
thread.Start("I've got some text");
Console.ReadLine();
}
private static void Work(object data)
{
string message = (string)data; // Wow, this is ugly
Console.WriteLine($"I, the thread write: {message}");
}
Casting is something you typically do not want to do.
What if someone passes something else which is not a string? As this seems not possible at first (because It is my method, I know what I do or The method is private, how should someone ever be able to pass anything to it?) you may possibly end up with exactly that case for various reasons. As some cases may not be a problem, others are. In such cases you will probably end up with an InvalidCastException which you probably will not notice because it simply terminates the thread.
As a solution you would expect to get a generic ParameterizedThreadStart delegate like ParameterizedThreadStart<T> where T would be the type of data you want to pass into the Work method. Unfortunately something like this does not exist (yet?).
There is however a suggested solution to this issue. It involves creating a class which contains both, the data to be passed to the thread as well as the method that represents the worker method like this:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
With this approach you would start the thread like this:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
So in this way you simply avoid casting around and have a typesafe way of providing data to a thread ;-)
here is the perfect way...
private void func_trd(String sender)
{
try
{
imgh.LoadImages_R_Randomiz(this, "01", groupBox, randomizerB.Value); // normal code
ThreadStart ts = delegate
{
ExecuteInForeground(sender);
};
Thread nt = new Thread(ts);
nt.IsBackground = true;
nt.Start();
}
catch (Exception)
{
}
}
private void ExecuteInForeground(string name)
{
//whatever ur function
MessageBox.Show(name);
}

Calling a function in class A from a thread in class B [C#]

Now with all the WaitOne and ManualResetEvent stuff working (thanks!) I've got one last problem, that is running a function in Class A from a thread which is part of Class B - again allow me to illustrate ...
Look at the function "DoIt(obejct param)" within class A, this needs to be called by class A (as shown) as well as by the thread in class B (as shown) ... how can this be accomplished? Would some form of delegates help?
class A
{
private ManualResetEvent manualResetEvent;
int counter = 0;
public A()
{
manualResetEvent = new ManualResetEvent(false);
B child = new B(manualResetEvent);
if (manualResetEvent.WaitOne(1000, false))
{
... do the work I was waiting on ...
}
... do more work ...
// Call the function DoIt from within A //
DoIt(param)
}
// This is the function that needs to be called from A and thread in B
void DoIt(object param)
{
counter++;
... do something with param with is local to A ...
}
};
Class B
{
private ManualResetEvent manualResetEvent;
public B(ManualResetEvent mre)
{
manualResetEvent = mre;
Thread childThread = new Thread(new ThreadStart(Manage));
childThread.IsBackground = true;
childThread.Name = "NamedPipe Manager";
childThread.Start();
private void Manage()
{
... do some work ...
... call some functions ...
// Calling the function from Class A, obviouslly doesn't work as-is
DoIt(param);
manualResetEvent.Set();
... do more work ...
... call more functions ...
}
}
};
Any one have any suggestions on how I can accomplish this task in a thread-safe manner?
Any help would be much appreciated.
Thanks,
Given your current design the simplest thing would be to pass in A to your object B, just like your doing with the manualresetevent:
B child = new B(this, manualResetEvent);
... etc...
Class B
{
private A parent;
private ManualResetEvent manualResetEvent;
public B(A p, ManualResetEvent mre)
{
parent = p;
manualResetEvent = mre;
... etc ...
private void Manage()
{
... do some work ...
... call some functions ...
parent.DoIt(param);
... etc...
Of course you need to mark A.DoIt as public.
As with your previous question, you have to pass the instance of A you want to call the method on to B's constructor.
I'm assuming there must be some higher class that manipulates both classes A and B? Such as a GUI Form or the main thread?
You could have an event defined for Class B that triggers when work should be done. Have your form listen for the event, and when it comes in call the function in Class A.
It sounds as if your two classes are highly dependent on one another. If work in B depends on results in A, and vise-versa, you may want to reconsider how modular your classes actually are.

How to create an asynchronous method

I have simple method in my C# app, it picks file from FTP server and parses it and stores the data in DB. I want it to be asynchronous, so that user perform other operations on App, once parsing is done he has to get message stating "Parsing is done".
I know it can achieved through asynchronous method call but I dont know how to do that can anybody help me please??
You need to use delegates and the BeginInvoke method that they contain to run another method asynchronously. A the end of the method being run by the delegate, you can notify the user. For example:
class MyClass
{
private delegate void SomeFunctionDelegate(int param1, bool param2);
private SomeFunctionDelegate sfd;
public MyClass()
{
sfd = new SomeFunctionDelegate(this.SomeFunction);
}
private void SomeFunction(int param1, bool param2)
{
// Do stuff
// Notify user
}
public void GetData()
{
// Do stuff
sfd.BeginInvoke(34, true, null, null);
}
}
Read up at http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx
try this method
public static void RunAsynchronously(Action method, Action callback) {
ThreadPool.QueueUserWorkItem(_ =>
{
try {
method();
}
catch (ThreadAbortException) { /* dont report on this */ }
catch (Exception ex) {
}
// note: this will not be called if the thread is aborted
if (callback!= null) callback();
});
}
Usage:
RunAsynchronously( () => { picks file from FTP server and parses it},
() => { Console.WriteLine("Parsing is done"); } );
Any time you're doing something asynchronous, you're using a separate thread, either a new thread, or one taken from the thread pool. This means that anything you do asynchronously has to be very careful about interactions with other threads.
One way to do that is to place the code for the async thread (call it thread "A") along with all of its data into another class (call it class "A"). Make sure that thread "A" only accesses data in class "A". If thread "A" only touches class "A", and no other thread touches class "A"'s data, then there's one less problem:
public class MainClass
{
private sealed class AsyncClass
{
private int _counter;
private readonly int _maxCount;
public AsyncClass(int maxCount) { _maxCount = maxCount; }
public void Run()
{
while (_counter++ < _maxCount) { Thread.Sleep(1); }
CompletionTime = DateTime.Now;
}
public DateTime CompletionTime { get; private set; }
}
private AsyncClass _asyncInstance;
public void StartAsync()
{
var asyncDoneTime = DateTime.MinValue;
_asyncInstance = new AsyncClass(10);
Action asyncAction = _asyncInstance.Run;
asyncAction.BeginInvoke(
ar =>
{
asyncAction.EndInvoke(ar);
asyncDoneTime = _asyncInstance.CompletionTime;
}, null);
Console.WriteLine("Async task ended at {0}", asyncDoneTime);
}
}
Notice that the only part of AsyncClass that's touched from the outside is its public interface, and the only part of that which is data is CompletionTime. Note that this is only touched after the asynchronous task is complete. This means that nothing else can interfere with the tasks inner workings, and it can't interfere with anything else.
Here are two links about threading in C#
Threading in C#
Multi-threading in .NET: Introduction and suggestions
I'd start to read about the BackgroundWorker class
In Asp.Net I use a lot of static methods for jobs to be done. If its simply a job where I need no response or status, I do something simple like below. As you can see I can choose to call either ResizeImages or ResizeImagesAsync depending if I want to wait for it to finish or not
Code explanation: I use http://imageresizing.net/ to resize/crop images and the method SaveBlobPng is to store the images to Azure (cloud) but since that is irrelevant for this demo I didn't include that code. Its a good example of time consuming tasks though
private delegate void ResizeImagesDelegate(string tempuri, Dictionary<string, string> versions);
private static void ResizeImagesAsync(string tempuri, Dictionary<string, string> versions)
{
ResizeImagesDelegate worker = new ResizeImagesDelegate(ResizeImages);
worker.BeginInvoke(tempuri, versions, deletetemp, null, null);
}
private static void ResizeImages(string tempuri, Dictionary<string, string> versions)
{
//the job, whatever it might be
foreach (var item in versions)
{
var image = ImageBuilder.Current.Build(tempuri, new ResizeSettings(item.Value));
SaveBlobPng(image, item.Key);
image.Dispose();
}
}
Or going for threading so you dont have to bother with Delegates
private static void ResizeImagesAsync(string tempuri, Dictionary<string, string> versions)
{
Thread t = new Thread (() => ResizeImages(tempuri, versions, null, null));
t.Start();
}
ThreadPool.QueueUserWorkItem is the quickest way to get a process running on a different thread.
Be aware that UI objects have "thread affinity" and cannot be accessed from any thread other than the one that created them.
So, in addition to checking out the ThreadPool (or using the asynchronous programming model via delegates), you need to check out Dispatchers (wpf) or InvokeRequired (winforms).
In the end you will have to use some sort of threading. The way it basically works is that you start a function with a new thread and it will run until the end of the function.
If you are using Windows Forms then a nice wrapper that they have for this is call the Background Worker. It allows you to work in the background with out locking up the UI form and even provides a way to communicate with the forms and provide progress update events.
Background Worker
.NET got new keyword async for asonchrynous functions. You can start digging at learn.microsoft.com (async). The shortest general howto make function asonchrynous is to change function F:
Object F(Object args)
{
...
return RESULT;
}
to something like this:
async Task<Object> FAsync(Object args)
{
...
await RESULT_FROM_PROMISE;
...
return RESULT;
}
The most important thing in above code is that when your code approach await keyword it return control to function that called FAsync and make other computation until promissed value has been returned and procede with rest of code in function FAsync.

Does C# have a "ThreadLocal" analog (for data members) to the "ThreadStatic" attribute?

I've found the "ThreadStatic" attribute to be extremely useful recently, but makes me now want a "ThreadLocal" type attribute that lets me have non-static data members on a per-thread basis.
Now I'm aware that this would have some non-trivial implications, but:
Does such a thing exist already built into C#/.net? or since it appears so far that the answer to this is no (for .net < 4.0), is there a commonly used implementation out there?
I can think of a reasonable way to implement it myself, but would just use something that already existed if it were available.
Straw Man example that would implement what I'm looking for if it doesn't already exist:
class Foo
{
[ThreadStatic]
static Dictionary<Object,int> threadLocalValues = new Dictionary<Object,int>();
int defaultValue = 0;
int ThreadLocalMember
{
get
{
int value = defaultValue;
if( ! threadLocalValues.TryGetValue(this, out value) )
{
threadLocalValues[this] = value;
}
return value;
}
set { threadLocalValues[this] = value; }
}
}
Please forgive any C# ignorance. I'm a C++ developer that has only recently been getting into the more interesting features of C# and .net
I'm limited to .net 3.0 and maybe 3.5 (project has/will soon move to 3.5).
Specific use-case is callback lists that are thread specific (using imaginary [ThreadLocal] attribute) a la:
class NonSingletonSharedThing
{
[ThreadLocal] List<Callback> callbacks;
public void ThreadLocalRegisterCallback( Callback somecallback )
{
callbacks.Add(somecallback);
}
public void ThreadLocalDoCallbacks();
{
foreach( var callback in callbacks )
callback.invoke();
}
}
Enter .NET 4.0!
If you're stuck in 3.5 (or earlier), there are some functions you should look at, like AllocateDataSlot which should do what you want.
You should think about this twice. You are essentially creating a memory leak. Every object created by the thread stays referenced and can't be garbage collected. Until the thread ends.
If you looking to store unique data on a per thread basis you could use Thread.SetData. Be sure to read up on the pros and cons http://msdn.microsoft.com/en-us/library/6sby1byh.aspx as this has performance implications.
Consider:
Rather than try to give each member variable in an object a thread-specific value, give each thread its own object instance. -- pass the object to the threadstart as state, or make the threadstart method a member of the object that the thread will "own", and create a new instance for each thread that you spawn.
Edit
(in response to Catskul's remark.
Here's an example of encapsulating the struct
public class TheStructWorkerClass
{
private StructData TheStruct;
public TheStructWorkerClass(StructData yourStruct)
{
this.TheStruct = yourStruct;
}
public void ExecuteAsync()
{
System.Threading.ThreadPool.QueueUserWorkItem(this.TheWorkerMethod);
}
private void TheWorkerMethod(object state)
{
// your processing logic here
// you can access your structure as this.TheStruct;
// only this thread has access to the struct (as long as you don't pass the struct
// to another worker class)
}
}
// now hte code that launches the async process does this:
var worker = new TheStructWorkerClass(yourStruct);
worker.ExecuteAsync();
Now here's option 2 (pass the struct as state)
{
// (from somewhere in your existing code
System.Threading.Threadpool.QueueUserWorkItem(this.TheWorker, myStruct);
}
private void TheWorker(object state)
{
StructData yourStruct = (StructData)state;
// now do stuff with your struct
// works fine as long as you never pass the same instance of your struct to 2 different threads.
}
I ended up implementing and testing a version of what I had originally suggested:
public class ThreadLocal<T>
{
[ThreadStatic] private static Dictionary<object, T> _lookupTable;
private Dictionary<object, T> LookupTable
{
get
{
if ( _lookupTable == null)
_lookupTable = new Dictionary<object, T>();
return _lookupTable;
}
}
private object key = new object(); //lazy hash key creation handles replacement
private T originalValue;
public ThreadLocal( T value )
{
originalValue = value;
}
~ThreadLocal()
{
LookupTable.Remove(key);
}
public void Set( T value)
{
LookupTable[key] = value;
}
public T Get()
{
T returnValue = default(T);
if (!LookupTable.TryGetValue(key, out returnValue))
Set(originalValue);
return returnValue;
}
}
Although I am still not sure about when your use case would make sense (see my comment on the question itself), I would like to contribute a working example that is in my opinion more readable than thread-local storage (whether static or instance). The example is using .NET 3.5:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Linq;
namespace SimulatedThreadLocal
{
public sealed class Notifier
{
public void Register(Func<string> callback)
{
var id = Thread.CurrentThread.ManagedThreadId;
lock (this._callbacks)
{
List<Func<string>> list;
if (!this._callbacks.TryGetValue(id, out list))
{
this._callbacks[id] = list = new List<Func<string>>();
}
list.Add(callback);
}
}
public void Execute()
{
var id = Thread.CurrentThread.ManagedThreadId;
IEnumerable<Func<string>> threadCallbacks;
string status;
lock (this._callbacks)
{
status = string.Format("Notifier has callbacks from {0} threads, total {1} callbacks{2}Executing on thread {3}",
this._callbacks.Count,
this._callbacks.SelectMany(d => d.Value).Count(),
Environment.NewLine,
Thread.CurrentThread.ManagedThreadId);
threadCallbacks = this._callbacks[id]; // we can use the original collection, as only this thread can add to it and we're not going to be adding right now
}
var b = new StringBuilder();
foreach (var callback in threadCallbacks)
{
b.AppendLine(callback());
}
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine(status);
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(b.ToString());
}
private readonly Dictionary<int, List<Func<string>>> _callbacks = new Dictionary<int, List<Func<string>>>();
}
public static class Program
{
public static void Main(string[] args)
{
try
{
var notifier = new Notifier();
var syncMainThread = new ManualResetEvent(false);
var syncWorkerThread = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(delegate // will create closure to see notifier and sync* events
{
notifier.Register(() => string.Format("Worker thread callback A (thread ID = {0})", Thread.CurrentThread.ManagedThreadId));
syncMainThread.Set();
syncWorkerThread.WaitOne(); // wait for main thread to execute notifications in its context
syncWorkerThread.Reset();
notifier.Execute();
notifier.Register(() => string.Format("Worker thread callback B (thread ID = {0})", Thread.CurrentThread.ManagedThreadId));
syncMainThread.Set();
syncWorkerThread.WaitOne(); // wait for main thread to execute notifications in its context
syncWorkerThread.Reset();
notifier.Execute();
syncMainThread.Set();
});
notifier.Register(() => string.Format("Main thread callback A (thread ID = {0})", Thread.CurrentThread.ManagedThreadId));
syncMainThread.WaitOne(); // wait for worker thread to add its notification
syncMainThread.Reset();
notifier.Execute();
syncWorkerThread.Set();
syncMainThread.WaitOne(); // wait for worker thread to execute notifications in its context
syncMainThread.Reset();
notifier.Register(() => string.Format("Main thread callback B (thread ID = {0})", Thread.CurrentThread.ManagedThreadId));
notifier.Execute();
syncWorkerThread.Set();
syncMainThread.WaitOne(); // wait for worker thread to execute notifications in its context
syncMainThread.Reset();
}
finally
{
Console.ResetColor();
}
}
}
}
When you compile and run the above program, you should get output like this:
alt text http://img695.imageshack.us/img695/991/threadlocal.png
Based on your use-case I assume this is what you're trying to achieve. The example first adds two callbacks from two different contexts, main and worker threads. Then the example runs notification first from main and then from worker threads. The callbacks that are executed are effectively filtered by current thread ID. Just to show things are working as expected, the example adds two more callbacks (for a total of 4) and again runs the notification from the context of main and worker threads.
Note that Notifier class is a regular instance that can have state, multiple instances, etc (again, as per your question's use-case). No static or thread-static or thread-local is used by the example.
I would appreciate if you could look at the code and let me know if I misunderstood what you're trying to achieve or if a technique like this would meet your needs.
I'm not sure how you're spawning your threads in the first place, but there are ways to give each thread its own thread-local storage, without using hackish workarounds like the code you posted in your question.
public void SpawnSomeThreads(int threads)
{
for (int i = 0; i < threads; i++)
{
Thread t = new Thread(WorkerThread);
WorkerThreadContext context = new WorkerThreadContext
{
// whatever data the thread needs passed into it
};
t.Start(context);
}
}
private class WorkerThreadContext
{
public string Data { get; set; }
public int OtherData { get; set; }
}
private void WorkerThread(object parameter)
{
WorkerThreadContext context = (WorkerThreadContext) parameter;
// do work here
}
This obviously ignores waiting on the threads to finish their work, making sure accesses to any shared state is thread-safe across all the worker threads, but you get the idea.
Whilst the posted solution looks elegant, it leaks objects. The finalizer - LookupTable.Remove(key) - is run only in the context of the GC thread so is likely only creating more garbage in creating another lookup table.
You need to remove object from the lookup table of every thread that has accessed the ThreadLocal. The only elegant way I can think of solving this is via a weak keyed dictionary - a data structure which is strangely lacking from c#.

Categories

Resources