Multithreading help in C# [FIXED]

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
tappatekie
Chaos Rift Junior
Chaos Rift Junior
Posts: 204
Joined: Mon Nov 21, 2011 3:01 pm
Current Project: Web browser from scratch
Favorite Gaming Platforms: SNES, PSP, PS1 and 3
Programming Language of Choice: C#
Location: A house near me
Contact:

Multithreading help in C# [FIXED]

Post 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)
Last edited by tappatekie on Sun Mar 31, 2013 7:58 am, edited 1 time in total.
User avatar
MarauderIIC
Respected Programmer
Respected Programmer
Posts: 3406
Joined: Sat Jul 10, 2004 3:05 pm
Location: Maryland, USA

Re: Multithreading help in C#

Post 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;
}
}
I realized the moment I fell into the fissure that the book would not be destroyed as I had planned.
qpHalcy0n
Respected Programmer
Respected Programmer
Posts: 387
Joined: Fri Dec 19, 2008 3:33 pm
Location: Dallas
Contact:

Re: Multithreading help in C#

Post 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".
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Multithreading help in C#

Post 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?
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
tappatekie
Chaos Rift Junior
Chaos Rift Junior
Posts: 204
Joined: Mon Nov 21, 2011 3:01 pm
Current Project: Web browser from scratch
Favorite Gaming Platforms: SNES, PSP, PS1 and 3
Programming Language of Choice: C#
Location: A house near me
Contact:

Re: Multithreading help in C#

Post 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.
qpHalcy0n
Respected Programmer
Respected Programmer
Posts: 387
Joined: Fri Dec 19, 2008 3:33 pm
Location: Dallas
Contact:

Re: Multithreading help in C#

Post 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.
tappatekie
Chaos Rift Junior
Chaos Rift Junior
Posts: 204
Joined: Mon Nov 21, 2011 3:01 pm
Current Project: Web browser from scratch
Favorite Gaming Platforms: SNES, PSP, PS1 and 3
Programming Language of Choice: C#
Location: A house near me
Contact:

Re: Multithreading help in C#

Post 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 :)
Post Reply