delegate callback and threading question

G

greg.merideth

I have a class that I've provided an event for to be called when the
processing in the class is complete (a callback). The class spins up a
series of threads for the background operation and I'm firing the
callback delgate from within one of the new threads. So far, all is
well but I'm curious as to what, threading wise, is going on there.

I'm instantiating the class in the app thread (say 1) and providing a
method to call when processing is done. My class is in thread 1 yet
I'm starting up threads 2 and 3. Thread 3 fires the callback delegate
when it's done processing so is that considered an unsafe thread
operation? Does .net shift the call back to thread 1 being the
delegate is part of the class declaration or is the call in my app
(thread 1) being called by thread 3 get 'moved' into thread 3's pool
meaning it would be unsafe to perform operations on data from within
the callback method?

Would it be more effective to switch the calls to async delegates and
let .net handle the threading and callback?
 
W

William Stacey [MVP]

It is a code block that gets run by the thread. There is no syncronization other then what you provide yourself.

Using code below, the Test.Run() callback is run 50 times. It could be started on multiple threads at any time.

Because of that I need to syncronize the private var count so to protect against any race condition that could occur.

Also note, because we are calling Run() on the class, Run has access to the private var "count" inside the class.

Does that help any?



private void button28_Click(object sender, EventArgs e)

{

Test t = new Test();

for(int i=0; i <50; i++)

{

ThreadPool.QueueUserWorkItem(t.Run);

}

}



public class Test

{

private int count;



public void Run(object tmp)

{

int newCount = Interlocked.Increment(ref count);

Console.WriteLine("Count:" + newCount);

}

}


--
William Stacey [MVP]

|I have a class that I've provided an event for to be called when the
| processing in the class is complete (a callback). The class spins up a
| series of threads for the background operation and I'm firing the
| callback delgate from within one of the new threads. So far, all is
| well but I'm curious as to what, threading wise, is going on there.
|
| I'm instantiating the class in the app thread (say 1) and providing a
| method to call when processing is done. My class is in thread 1 yet
| I'm starting up threads 2 and 3. Thread 3 fires the callback delegate
| when it's done processing so is that considered an unsafe thread
| operation? Does .net shift the call back to thread 1 being the
| delegate is part of the class declaration or is the call in my app
| (thread 1) being called by thread 3 get 'moved' into thread 3's pool
| meaning it would be unsafe to perform operations on data from within
| the callback method?
|
| Would it be more effective to switch the calls to async delegates and
| let .net handle the threading and callback?
|
 
M

Michael Nemtsev

Hello William Stacey [MVP],

It may help, untill he freeze all 25 threads or exit from app and wonders
why all his theads are abandoned ;)

W> It is a code block that gets run by the thread. There is no
W> syncronization other then what you provide yourself.
W>
W> Using code below, the Test.Run() callback is run 50 times. It could
W> be started on multiple threads at any time.
W>
W> Because of that I need to syncronize the private var count so to
W> protect against any race condition that could occur.
W>
W> Also note, because we are calling Run() on the class, Run has access
W> to the private var "count" inside the class.
W>
W> Does that help any?
W>
W> private void button28 Click(object sender, EventArgs e)
W>
W> {
W>
W> Test t = new Test();
W>
W> for(int i=0; i <50; i++)
W>
W> {
W>
W> ThreadPool.QueueUserWorkItem(t.Run);
W>
W> }
W>
W> }
W>
W> public class Test
W>
W> {
W>
W> private int count;
W>
W> public void Run(object tmp)
W>
W> {
W>
W> int newCount = Interlocked.Increment(ref count);
W>
W> Console.WriteLine("Count:" + newCount);
W>
W> }
W>
W> }
W>
W> W> |I have a class that I've provided an event for to be called when the
W> | processing in the class is complete (a callback). The class spins
W> up
W> a
W> | series of threads for the background operation and I'm firing the
W> | callback delgate from within one of the new threads. So far, all
W> is
W> | well but I'm curious as to what, threading wise, is going on there.
W> |
W> | I'm instantiating the class in the app thread (say 1) and providing
W> a
W> | method to call when processing is done. My class is in thread 1
W> yet
W> | I'm starting up threads 2 and 3. Thread 3 fires the callback
W> delegate
W> | when it's done processing so is that considered an unsafe thread
W> | operation? Does .net shift the call back to thread 1 being the
W> | delegate is part of the class declaration or is the call in my app
W> | (thread 1) being called by thread 3 get 'moved' into thread 3's
W> pool
W> | meaning it would be unsafe to perform operations on data from
W> within
W> | the callback method?
W> |
W> | Would it be more effective to switch the calls to async delegates
W> and
W> | let .net handle the threading and callback?
W> |
---
WBR,
Michael Nemtsev :: blog: http://spaces.msn.com/laflour

"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsch
 
W

William Stacey [MVP]

| It may help, untill he freeze all 25 threads or exit from app and wonders
| why all his theads are abandoned ;)

You always must deal with these issues, and others, when using threads. But
that reply does not help with the OT.
 
G

greg.merideth

Not quite was I was looking, let me try it with code.

class Main {
SomeClass a = new SomeClass();
a.EventComplete += new EventComplete(MainsCallback);
loop {
while doing other work on "this thread"
}
void MainsCallback() {
Console.WriteLine("done"); <-- what thread will this execute on?
}
}

Here class Main creates an instance of "SomeClass" and attaches to it's
public event a method from within itself (delegate callback). "Main"
is running on Thread 1 (assume).

class SomeClass {
public event DelEvent EventComplete;
SomeClass() {
Start.Thread2(); // start a new thread here - Thread 2
}
void Thread2() {
for(whatever)
EventComplete(); <-- call the delegate method to signal when were
done
}
}

SomeClass starts a new Thread from within itself, Thread 2. When
Thread 2 is done doing it's thing, it triggers the delegate method by
calling it's EventComplete(), a method, in Main, on Thread 1.

The question is, in what context will MainsCallback be executed? Since
Main (Thread 1) created the instance of SomeClass will it execute on T1
or will MainsCallback be executed under T2's thread?

Bizarringly when I print out the Hash of the CurrentThread context,
*sometimes* I get "1" and sometimes I get "2" meaning it's being run on
whatever thread the system feels like running it on?
 
J

Jon Skeet [C# MVP]

(e-mail address removed) wrote:

The question is, in what context will MainsCallback be executed? Since
Main (Thread 1) created the instance of SomeClass will it execute on T1
or will MainsCallback be executed under T2's thread?

Always on the thread which calls the delegate - T2 in this case.
Bizarringly when I print out the Hash of the CurrentThread context,
*sometimes* I get "1" and sometimes I get "2" meaning it's being run on
whatever thread the system feels like running it on?

Could you post a short but complete example which demonstrates that? It
sounds unlikely.

Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top