Page 1 of 1

Multithreading help in C# [FIXED]

Posted: Sat Mar 23, 2013 8:30 pm
by tappatekie
Hey guys, I haven't really touched on getting multiple threads to synchronize in C# but I need to have it.

I need code like this (little mockup completely ignoring CPU load costs)
The code currently just does not work, it works fine until another thread calls Add() and everything dead locks. (it's called from within a delegate called in DoStuffWithArray())

Code: Select all

public myClass() { 
       new Thread(new ThreadStart() { while(true) { DoStuffWithArray(); })).Start();
}
private myObject[] array = new myObject[0];

void Add(myObject arr) { 
     lock(array) {
          //add to array
     }
}
void DoStuffWithArray() { 
     lock(array) {
          //do stuff with every object

          //clear object list
          array = new myObject[0]; //I think this would cause it?
     }
}
I've tried narrowing down the two functions into a single function with one lock, but it still throws off syncronization and don't know how to impliment a mutex.

Also, this needs to be high performance code and I'm aware of the performance lost by using "lock" but I have to sacrifice performance for correct syncronization.

I have also tried but still does'nt work...

Code: Select all

static object l = new object();
void lockMe() { lock(l) { } }
As far as I'm aware, threads created within the lock and access the same function does not itself get locked.

Please help! :) Could it be a gliche with the actual v2.0 .Net framework? (System.Monitor class)

Re: Multithreading help in C#

Posted: Sat Mar 23, 2013 9:35 pm
by MarauderIIC
Threading in general varies when you call lock on the same object that is already locked. It is possible in C# that performing lock(array) within a lock(array) does not release locks correctly. Suggest attempting to refactor such that you do not perform a lock(array) inside a lock(array), as you are doing when you perform a lock from a delegate that is inside another function that is entirely encased in a lock.

You should lock as little as possible.

For instance,

GOOD:

Code: Select all

func() {
a = 5;
b = 6;
lock(array) { array = morearray; }
c = 7
}
BAD: <- You are doing this inside DoStuffWithArray

Code: Select all

func() {
lock(array) {
a = 5;
b = 6;
array = morearray;
c = 7;
}
}

Re: Multithreading help in C#

Posted: Sun Mar 24, 2013 12:19 am
by qpHalcy0n
I'm having an extremely difficult time following this logic, but...

It looks like your handler never returns. As implemented, of course it will deadlock. It's going to go into a spin lock and never get out. As such, since the thread handler will never return, when you call add, it will never enter the critical section. Entering a critical section from another is defined behavior and should never cause a problem UNLESS you create the conditions in which a deadlock can happen.

I think this should really be "re-thunk".

Re: Multithreading help in C#

Posted: Sun Mar 24, 2013 10:54 am
by dandymcgee
I agree with qp.

Also, rather than providing an abstract example that demonstrates the misbehavior, it would be helpful if you could explain what problem you are really trying to solve. In what context is this threading code to be running?

Re: Multithreading help in C#

Posted: Sun Mar 24, 2013 1:29 pm
by tappatekie
dandymcgee wrote:I agree with qp.

Also, rather than providing an abstract example that demonstrates the misbehavior, it would be helpful if you could explain what problem you are really trying to solve. In what context is this threading code to be running?
Basically I have an EventStack class which fires every message for a control or window asyncronous to a thread so that thread won't lock or cause stack overflow. E.g calling Size within Render which when you set size, the render is fired again.

I think I have found the source of the issue, it's not the locking since I've tried about 10 threads sending a message constantly and does not cause any lockups (including calls to the same locking method within a lock) so I think it's doing what I want it to do, but the callback processing the message (native win32 message). For some reason, it's always WM_NCACTIVATE that locks up the entire calling stack which gives the impression it's locking (DefWindowProc never returns when this message is sent). Could it be that i'm calling from a seperate thread and it must be the thread that created the control calling it instead? If so, how do I invoke a delegate on a threads behalf? I've tried ExecutionContext.Run and Context.DoCallback but it still fires from the other thread, I need the equivilent of System.Windows.Control.Invoke.

The source code for this class is here: http://pastebin.com/iLM8WZUB oh and SendEvent(ref EventTranslation) is the function which is called when a window message comes in so the parent thread waits for the message to be processed.

Re: Multithreading help in C#

Posted: Sun Mar 24, 2013 7:34 pm
by qpHalcy0n
I mean, based on the code presented, you're getting absolutely no benefit to threading here. Almost your entire code is one big critical section. In that case, you have minimal to no benefit at all, and may in fact incur a performance hit from that overhead. Event processing at least in the Win32 case is already pretty damned efficient and is already asynchronous and as such is not a good candidate for multithreading.

As was alluded to in a prior post, you REALLY need to ensure that you lock or enter a critical section (hold some resource) for as absolutely minimal a time as possible. If you have to hold it for the entire event processing routine....there's absolutely no point whatsoever.

Re: Multithreading help in C#

Posted: Mon Mar 25, 2013 3:39 am
by tappatekie
qpHalcy0n wrote:I mean, based on the code presented, you're getting absolutely no benefit to threading here. Almost your entire code is one big critical section. In that case, you have minimal to no benefit at all, and may in fact incur a performance hit from that overhead. Event processing at least in the Win32 case is already pretty damned efficient and is already asynchronous and as such is not a good candidate for multithreading.

As was alluded to in a prior post, you REALLY need to ensure that you lock or enter a critical section (hold some resource) for as absolutely minimal a time as possible. If you have to hold it for the entire event processing routine....there's absolutely no point whatsoever.
I have to do it this way because of platform independence but I need to rethink it I know :)

I've come to a realization of what I'm actually doing and need to do, there is only 1 handle and 1 thread processing the entire window message queue, for reasons of explanation, i'm not going to go into controls. I don't need the EventStack class anymore but instead, the window SendEvent would basically call RegisterMessage and PostMessage to send the event to the correct control under the parent thread of the window.

The Control class is itself completely platform independant but the Window class is platform locked, so that is why a control would have to send a message up to the window.

Sorry if I sound like I don't know anything btw :)