Cross-thread methods
Hi all,
I was wondering if static methods work across threads ? So if I create a class in one thread and it has static methods and try to call these from another thread, is is supposed to work? If not, what techniques can I use for cross-thread communication? Thanks.
Regards
[293 byte] By [
gamehack] at [2007-11-19 10:44:08]

# 1 Re: Cross-thread methods
Did you try doing it? I guess it should work.
# 2 Re: Cross-thread methods
Static methods work across threads.
There is no class instance in c# (like in Smalltalk), so classes cannot be created.
Static methods can be called without creating any object.
Instance methods on an object created on one thread can be called by any other thread that has a reference to the object.
Objects and static methods meant to be called by many threads should be thread-safe, access to them needs to be syncrhonized to avoid dead-locks, concurrent updates etc.
# 3 Re: Cross-thread methods
you cant syncronize a static method, because to do so you need an instance of something.
using delegates will allow you to syncronize calls, and they are thread safe.
# 4 Re: Cross-thread methods
Mad hatter - yes you can synchronise a static member by using a static Mutex.
Firstly if gamehack doesn't know what synchronisation is I'll give a small (very small) explanation.
Synchronisation is the process of making sure a section of code isn't executed at the same time by different threads.
The classic example of this is when you have one method called by different threads which accesses a single instance of a variable.
Also, as soon as you throw multithreading into an application be prepared : it adds about an order of magnitude of complexity to the application immediately. Things will go wrong for no reason. And the problems will not be reproducable - you are not dealing with a simple line-by-line execution of code with multi-threading. You're dealing with concurrency.
If you don't understand threads and are learning gamehack I would STRONGLY recommend you read up on concurrency and synchronisation - go out on google and search for "synchronising threads" or "concurrency" or something similar.
Now, to answer Mad Hatter.
You're probably thinking of the 'lock' statement. This isn't the only way of synchronising threads in C#.
The 'lock' keyword does requires an instance of an object but the System.Threading namespace contains classes to do synchronisation without the need for an instance of a class.
Consider this : it is synchronised :
public class SynchronisedStaticInt
{
static private int m_nValue = 0;
static private Mutex m_mutex = new Mutex();
static public int Value
{
get
{
m_mutex.WaitOne();
int nValue = m_nValue;
m_mutex.ReleaseMutex();
return nValue;
}
set
{
m_mutex.WaitOne();
m_nValue = value;
m_mutex.ReleaseMutex();
}
}
Now, I personally have IDisposable classes to do the WaitOne() and ReleaseMutex() calls :
public class LockMutex : IDisposable
{
private Mutex m_mutex = null;
public LockMutex(Mutex mutex)
{
m_mutex = mutex;
m_mutex.WaitOne();
}
// from IDisposable
public void Dispose()
{
m_mutex.ReleaseMutex();
}
}
Then the above code looks like this :
public class SynchronisedStaticInt
{
static private int m_nValue = 0;
static private Mutex m_mutex = new Mutex();
static public int Value
{
get
{
using (MutexLock lockMutex = new MutexLock(m_mutex))
{
return m_nValue;
}
}
set
{
using (MutexLock lockMutex = new MutexLock(m_mutex))
{
m_nValue = value;
}
}
}
}
I think you'll agree it's very readable.
I've written an article about this very technique, but it doesn't deal with concurrency. But it does deal with the how the class I've just specified above works and the "using" keyword.
http://www.dev-archive.com/Csharp/Csharp/cs_syntax/interfaces/article.php/c8679/
Darwen.
# 5 Re: Cross-thread methods
I stand corrected. I didnt think that would work. I thought static instances are subject to finalization adhoc. especially if your class containing a static method to be used is disposable, then any static members you once had are deleted and you get an null object reference exception when trying to lock / unlock yourself.
using static methods are not a good idea. you're not guarenteed to have the same static instance anywhere, which makes true syncronization (IMO) impossible.
using a singleton would be a better approach if static methods are perferred (that way you can ensure what you need is available). this way you can guarentee that what you are calling is what you want.
I still say that delegates are the better solution.
public delegate ThreadCrossover(params object[] data);
ClassA a = new ClassA();
a.DoProcess = new ThreadCrossover(TCHandler);
Thread t = new Thread(a.ThreadProc);
t.Start();
// ...
private void TCHandler(params object[] data) {
// ... lock & handle between whomever
}
then interprocess communication between any thread can be safely invoked within a single thread. adding more functionality you can add communication in both directions directly instead of trying to handle something within a static method.
# 6 Re: Cross-thread methods
you are missing a very important point
its correct that for static fields we don't have an instance of the type in the heap and, therefore, there is no SyncBlock to be used or object reference to pass to Monitor's Enter and Exit methods.
but the block of memory that contains a type's type descriptor is an object in the heap ,which each of them has a MethodTablePointer field and a SyncBlockIndex field. This means that a SyncBlock can be associated with a type and a reference to the type object can be passed to the Monitor's Enter and Exit methods.
so even for static fields we can find something on the heap which is typeof(theClass)
this is a simple example that shows itclass Transaction {
// Private field holding the time of
// the last transaction performed
private static DateTime timeOfLastTransaction;
public static void PerformTransaction() {
lock (typeof(Transaction)) {
// Perform the transaction...
// Record time of the most recent transaction
timeOfLastTransaction = DateTime.Now;
}
}
// Public read-only property returning
// the time of the last transaction
public static DateTime LastTransaction {
get {
lock (typeof(Transaction)) {
// Return the time of the last transaction
return timeOfLastTransaction;
}
}
}
}its reference
http://msdn.microsoft.com/msdnmag/issues/03/01/NET/
