System.Thread and multiple method calls

P

Paul Schwann

Hi group,

I am relatively new to C# (although I have a lot of programming
excperience in other languages like Java and C). Currently I am
searching for a solution to this problem:

Suppose you have 3 methods A, B and C. All of them shall be run
threaded (I/O tasks) and one after another. I can create a thread and
schedule one method just like:

Thread t = new Thread(A);

But how do I add the other 2 methods? Can this be done somehow with
the .NET Library classes or do I have to create my own "Thread-Method-
Manager" for this purpose? I also would like to add and remove the
methods being executed dynamically.

Thansk for your ideas!

Regards,
Paul
 
S

Scott Roberts

Paul Schwann said:
Hi group,

I am relatively new to C# (although I have a lot of programming
excperience in other languages like Java and C). Currently I am
searching for a solution to this problem:

Suppose you have 3 methods A, B and C. All of them shall be run
threaded (I/O tasks) and one after another. I can create a thread and
schedule one method just like:

Thread t = new Thread(A);

But how do I add the other 2 methods? Can this be done somehow with
the .NET Library classes or do I have to create my own "Thread-Method-
Manager" for this purpose? I also would like to add and remove the
methods being executed dynamically.

Thansk for your ideas!

Regards,
Paul

Hi Paul,

Not so sure about Java and C, but in every language I've ever worked in a
thread has a single starting point and linear execution path, just like the
"main" program thread. So, in your case, if you want to execute methods A,
B, and C, you would need to create a new method D that calls A, B, and C and
use method D as your thread proc. You can, of course, pass parameters to
method D to identify which other methods to be executed.

I suppose you *could* implement some sort of message pump (like the "main"
program thread usually has) and dynamically execute methods based on
messages, but that seems like it may be overkill, depending on what you are
trying to accomplish.

Scott
 
P

Paul Schwann

Hi Scott,

thanks for your reply! Implementing such a method D by myself is what
I more or less will do now. I just thought how nice it would be based
on some kind of delegates... Like

Thread t = new Thread();
t.executeThis += A;
t.start();
....
t.executeThis += B;
....
t.executeThis += C;
....
t.executeThis -= A;

.... You get the idea... :)

Regards,
Paul
 
J

Jon Skeet [C# MVP]

Scott Roberts said:
Not so sure about Java and C, but in every language I've ever worked in a
thread has a single starting point and linear execution path, just like the
"main" program thread. So, in your case, if you want to execute methods A,
B, and C, you would need to create a new method D that calls A, B, and C and
use method D as your thread proc. You can, of course, pass parameters to
method D to identify which other methods to be executed.

Yup. One "wrinkle" to .NET is that what you pass in when you create a
thread is a delegate - and delegates can have multiple targets. I've
*never* used ThreadStart in this way before, but it will work. It's
pretty odd...

using System;
using System.Threading;

class Test
{
static void Main()
{
ThreadStart start = null;

start += A;
start += B;
start += C;

new Thread(start).Start();
}

static void A()
{
Console.WriteLine ("A");
}

static void B()
{
Console.WriteLine ("B");
}

static void C()
{
Console.WriteLine ("C");
}
}

Note that you can't add to the list of methods to execute after you've
started the thread though.
I suppose you *could* implement some sort of message pump (like the "main"
program thread usually has) and dynamically execute methods based on
messages, but that seems like it may be overkill, depending on what you are
trying to accomplish.

Again, I agree. Fortunately if the OP *does* need to do this, it's not
too hard to do with a producer/consumer queue.
 
J

Jon Skeet [C# MVP]

Paul Schwann said:
thanks for your reply! Implementing such a method D by myself is what
I more or less will do now. I just thought how nice it would be based
on some kind of delegates... Like

<snip>

Yup, see my recent post for a complete example. You should probably
comment this in your code, however - it's not a common pattern. (Quite
a neat one though.)
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,


You are saying that the 3 methods needs to be run one after the other, what
if you create a new method (can be anonymous) that call the 3 methods?

void DoIt()
{
A();
B();
C();
}


and then is that method the one that you start the thread with?
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,


--
Ignacio Machin
http://www.laceupsolutions.com
Mobile & warehouse Solutions.
Yup. One "wrinkle" to .NET is that what you pass in when you create a
thread is a delegate - and delegates can have multiple targets. I've
*never* used ThreadStart in this way before, but it will work. It's
pretty odd...

I have never though of this. Of course as ThreadStart is a delegate you can
do it. I wander what would happen if one method throw an exception ....
 
J

Jon Skeet [C# MVP]

[Side point - Ignacio, all your posts end up with a signature before
all of the quoted text. That means when I start to reply, all I end up
with is "Hi". Could you either remove the signature separator or make
sure it ends up after the body?]

I have never though of this. Of course as ThreadStart is a delegate
you can do it. I wander what would happen if one method throw an
exception ....

I would expect it to behave as any other delegate - if there are
actions of A, B, C and if B throws an exception, C won't be executed. I
can't see any documentation about it, however...
 
I

Ignacio Machin \( .NET/ C# MVP \)

Jon Skeet said:
[Side point - Ignacio, all your posts end up with a signature before
all of the quoted text. That means when I start to reply, all I end up
with is "Hi". Could you either remove the signature separator or make
sure it ends up after the body?]


Sorry for that, no idea why OE place the signature at the top instead of at
the botton of the message. Will have to dig around to see if I can change it
somewhere.

Ignacio Machin
http://www.laceupsolutions.com
Mobile & warehouse Solutions.
 
P

Paul Schwann

Hi Ignacio,

basically, you are right:
You are saying that the 3 methods needs to be run one after the other, what
if you create a new method (can be anonymous) that call the 3 methods?

void DoIt()
{
    A();
    B();
    C();

}

But I need a way t configure the "three" methods such that I can say
when (and when not) they run. I want to select them during runtime and
thus, need something more dynamic than just a function D().

If you have any ideas how to do this nicely, please let me know!

Regards,
Paul
 
P

Peter Duniho

But I need a way t configure the "three" methods such that I can say
when (and when not) they run. I want to select them during runtime and
thus, need something more dynamic than just a function D().

If you have any ideas how to do this nicely, please let me know!

Possibly you hadn't read Jon's reply by the time you replied to Ignacio's
post?

If Jon's suggestion doesn't suit your needs, you should be more specific
about why not.

As Jon's example code illustrates, at the time that you create the
ThreadStart delegate, you can add as many methods to the delegate as you
need to. Then use that to create the thread. The delegates will be run
in the order that they were combined (so in the code Jon posted, in the
order: A, B, then C).

His other suggestion, mirroring Scott's comment about a producer/consumer
type implementation is valid as well. Which is more useful to you will
depend on your exact needs (that is, do you know the methods and their
order prior to creating the thread?)

Pete
 
P

Paul Schwann

Hi Pete and all the others,

thanks a lot for your valuable input! Although Jon's solution is
almost perfect, it does'nt work for me. I have to be able to add and
remove any of the A, B, C, ... functions form the delegate while the
thread is *already running*. I think I will implement my own way of
doing this. Here is my first idea (sort of Java/Pseudo code):

class MyThreadManager extends Thread {
List<Runnable> executeThis;

public void run() {
for (runnable in executeThis) {
runnable.run();
}
}

synchronized addExecutable(Runnable r) {...}
synchronized removeExecutable(Runnable r) {...}
}

Just an idea.... :)

Regards,
Paul
 
P

Peter Duniho

Hi Pete and all the others,

thanks a lot for your valuable input! Although Jon's solution is
almost perfect, it does'nt work for me. I have to be able to add and
remove any of the A, B, C, ... functions form the delegate while the
thread is *already running*. I think I will implement my own way of
doing this. Here is my first idea (sort of Java/Pseudo code): [snip]

The code you posted is not far off from the producer/consumer suggestion.
However, one thing you're going to run into is the problem of modifying a
List<> instance while you've got an enumerator operating on it.

You could address that by enumerating by an index that's stored not as a
local variable but a member variable of the implementation class, so that
it can be adjusted to account for methods removed during execution.

The other issue you'll have to solve is what to do when the client code
tries to remove a method that's already running. Simplest would be to
just ignore that, let the method be removed from the list without
affecting the current execution of it. An alternative would be to make
the methods cancellable, with removal causing a cancellation, but since
that would complicate an already-complicated design, I think it'd be
better if you can do without that feature.

I do think you should consider carefully whether you really must have the
behavior you're asking about. There's nothing wrong with it as long as
that's really the most straightforward and clean way to accomplish
whatever it is you're trying to accomplish. But it's definitely an
unusual request, and my experience has been that many (but not all, of
course) unusual requests represent a design choice that could have been
made differently, in a way that leads to a simpler implementation.

This latter point is especially true when the unusual request involves
creating a complicated situation such as this one. A straight
producer/consumer design wouldn't be exactly what you've asked for, but it
would be much simpler architecturally. Neither are particularly difficult
to implement, but conceptually having a mutable list of execution methods
that can change while it's being enumerated is at the very least
complicated, and at worst could lead to puzzling or subtle bugs that are
very dependent on the timing of the code elsewhere. You should be sure
that this is a maintenance cost that is worth whatever advantage that
design has for you.

Pete
 
P

Paul Schwann

Hi Peter,

thanks a lot for your detailed answer. I appreciate it a lot! I am
aware of the fact that the request I have is somewhat unusal. This is
due to the implementation of the underlying library which will be
called by all of those A, B, C... methods I mentioned.

The situation is such that this library is not thread safe in any way.
Thus, only one thread shall access it at at time.

On the other hand we have those A, B, C methods which belong to
different parts of the application and do different things of course.
Nevertheless, they all access this library sooner or later.

All these methods A, B, C... do repeating things once or twice a
second. In a perfect world, I would just put each of these functions
in a timer and I am done. But I cannot due to the lack of thread
safety and inability of reentranace of the library methods.

---

About my little code snippet: Of cousre, reading/writing of this
List<> must be thread safe. Thus, my idea is that in a synchronized
part of the code, the list is copied and this copy is used for the
enumaration.
Thus, the original List<> can be manipulated at any time except for
the very short time period required to create the copy.
Once a method is removed or added to the List<>, it will executed the
NEXT time the for.. loop runs. It has no impact on the current loop-
run. This behavior is exceptable for my application.

---

If you have any comments on this or a better suggestion to solve it, I
would like to hear it and discuss it!

Regards,
Paul
 
P

Paul Schwann

Hi Peter,

thanks a lot for your detailed answer. I appreciate it a lot! I am
aware of the fact that the request I have is somewhat unusal. This is
due to the implementation of the underlying library which will be
called by all of those A, B, C... methods I mentioned.

The situation is such that this library is not thread safe in any way.
Thus, only one thread shall access it at at time.

On the other hand we have those A, B, C methods which belong to
different parts of the application and do different things of course.
Nevertheless, they all access this library sooner or later.

All these methods A, B, C... do repeating things once or twice a
second. In a perfect world, I would just put each of these functions
in a timer and I am done. But I cannot due to the lack of thread
safety and inability of reentranace of the library methods.

---

About my little code snippet: Of cousre, reading/writing of this
List<> must be thread safe. Thus, my idea is that in a synchronized
part of the code, the list is copied and this copy is used for the
enumaration.
Thus, the original List<> can be manipulated at any time except for
the very short time period required to create the copy.
Once a method is removed or added to the List<>, it will executed the
NEXT time the for.. loop runs. It has no impact on the current loop-
run. This behavior is exceptable for my application.

---

If you have any comments on this or a better suggestion to solve it, I
would like to hear it and discuss it!

Regards,
Paul
 
P

Peter Duniho

Hi Peter,

thanks a lot for your detailed answer. I appreciate it a lot! I am
aware of the fact that the request I have is somewhat unusal. This is
due to the implementation of the underlying library which will be
called by all of those A, B, C... methods I mentioned.

The situation is such that this library is not thread safe in any way.
Thus, only one thread shall access it at at time.

There are other ways to accomplish that. Better ones, IMHO.
On the other hand we have those A, B, C methods which belong to
different parts of the application and do different things of course.
Nevertheless, they all access this library sooner or later.

It's true that serializing the calls to those methods will ensure
synchronization of access to the library. However, your description
implies that accessing the library isn't _all_ that those methods are
doing, and so of course if you serialize the methods you fail to take
advantage of any parallelism that might otherwise exist between the
methods (e.g. if two or more are doing i/o, or if you have a computer
system with more than one CPU core).

It would be simplest if you could simply add the synchronization to the
methods being called. However, I understand that it's possible those
methods might have numerous calls to the library written into the code and
it would be tedious and error-prone to try to synchronize each and every
call. If that's the case, then the better alternative would be to modify
the library so that it's thread-safe. Assuming that you don't have
control over the library itself, the way to do this would be to create a
wrapper class that accesses the library, and which includes the
synchronizing code itself, locking around each call into the library.

By the way, by "synchronizing" I just mean any mechanism available in .NET
for accomplishing this. A very common scenario is to create a plain
"object" type instance (e.g. "object _objLock = new object()") and use
that as the parameter for a "lock()" statement, with the call to the
library inside the block protected by the lock.
[...]
About my little code snippet: Of cousre, reading/writing of this
List<> must be thread safe. Thus, my idea is that in a synchronized
part of the code, the list is copied and this copy is used for the
enumaration.
Thus, the original List<> can be manipulated at any time except for
the very short time period required to create the copy.
Once a method is removed or added to the List<>, it will executed the
NEXT time the for.. loop runs. It has no impact on the current loop-
run. This behavior is exceptable for my application.

I don't understand. If that behavior is acceptable for the application,
then why not just have a ThreadStart delegate that can be modified by code
wanting to add or remove these methods, and then use that delegate when
you start the thread? This would be a variation on the implementation Jon
suggests, except that instead of creating the delegate in the method that
starts the thread, you'd keep the delegate variable somewhere more
accessible to the code that wants to add or remove methods.

Delegates are already immutable and behave pretty much like what you've
suggested above (a new copy is made each time something's added or
removed, with just the reference being replaced) so if you just provide a
method to lock around the changes to the delegate, you'll be assured that
when you go to use the delegate it's in a usable state and won't change
during the execution of the thread itself.

Of course, this is very similar to what an event does, and you may find
that it works even better to define the delegate variable as an event, and
pass a copy of that event variable as the ThreadStart delegate. For
example:

event ThreadStart LibraryAccess;

void Start()
{
Thread thread = new Thread(LibraryAccess);

thread.Start();
}

Then you'd just use syntax like this:

LibraryAccess += A;
LibraryAcdess += B;

LibraryAccess -= A;
// etc.

To add and remove the methods. Each time the thread is created, it would
get the current copy of the event as a ThreadStart delegate and use that
to execute the thread.

Of course, if you are running these methods on a relatively frequent
basis, it may make sense to use the thread pool rather than creating a new
thread each time. But I think if they only get run every couple of
seconds and the execution itself isn't extremely brief, creating a
dedicated thread is probably okay.

Of course, all of this latter discussion assumes that you cannot make the
library thread-safe and must serialize the execution of these methods. As
I mentioned above, I think a better approach would be in fact to not
serialize the execution of the methods (possibly using the thread pool to
execute them) and make the library thread-safe somehow, even if that means
writing a whole new class that wraps the library and synchronizes access
to it for you.

Pete
 
P

Paul Schwann

Hi there,

I had the chance to code something which apparently does what I want
it to do :) Now, I have a couple of questions where I cannot find
answers. But the code first:

using System;

namespace test {
public class Test {
public static void Main() {

Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().Location);

new Test();
}

private Test() {
ThreadManager tm = new ThreadManager();
tm.e = A;

System.Threading.Thread.Sleep(500);

tm.e -= A;

System.Threading.Thread.Sleep(500);

tm.e += A;
tm.e += B;

System.Threading.Thread.Sleep(500);

tm.e += C;

System.Threading.Thread.Sleep(500);

tm.e -= A;
tm.e -= B;

System.Threading.Thread.Sleep(500);

tm.dispose();
}

private void A() {
Console.Write("A");
}

private void B() {
Console.Write("B");
}

private void C() {
Console.Write("C");
}
}

public class ThreadManager {
private bool disposed;

public delegate void execute();

public execute e;

public ThreadManager() {
disposed = false;
System.Threading.Thread t = new
System.Threading.Thread(run);
t.Start();
}

private void run() {
while (!disposed) {
if (e != null) {
e();
}
}
}

public void dispose() {
disposed = true;
}
}
}

The class ThreadManager is the heart of this little example above. It
basically uses a delegate to handle all the desired methods being
called. And here are the questions:

1. Is adding and removing methods from the delegate thread safe?
2. If not, how do I synchronize this tm.e += ... and tm.e -=
operations?

Thanks for any advices!

Regards,
Paul
 
J

Jon Skeet [C# MVP]

The class ThreadManager is the heart of this little example above. It
basically uses a delegate to handle all the desired methods being
called. And here are the questions:

1. Is adding and removing methods from the delegate thread safe?

Sort of. The thing is, you never actually add a method to an existing
delegate - you replace an existing one.
2. If not, how do I synchronize this tm.e += ... and tm.e -=
operations?

Turn the public field (argh!) into an event, and make the event itself
thread-safe, as per
http://pobox.com/~skeet/csharp/threads/lockchoice.shtml

Public writable fields are always going to have thread-safety issues.
 
P

Peter Duniho

[...]
The class ThreadManager is the heart of this little example above. It
basically uses a delegate to handle all the desired methods being
called. And here are the questions:

1. Is adding and removing methods from the delegate thread safe?

Yes and no. In the code you posted, all of the changes to the delegate
are done in a single thread. That's safe.

But no, if you are changing the delegate from multiple threads, then two
different threads could race while trying to change the delegate. The
thread that loses the race actually wins, as its copy of the new delegate
is the one that will get assigned, overwriting the change of the other
thread.
2. If not, how do I synchronize this tm.e += ... and tm.e -=
operations?

Well, this is why I suggested in my previous post that in this case, you
might find it useful to just use an event as the ThreadStart delegate. It
already has this thread-safety built in.

That said, it's easy enough to do yourself if you want. As I also wrote
in that same post, you can use the lock() statement to protect accesses
that change the delegate, ensuring that any thread changing the delegate
can always take into account the changes some other thread is making.

Finally, the code you posted has a bug:

private void run() {
while (!disposed) {
if (e != null) {
e();
}
}
}

You need to store the value of "e" before checking it for null, or put a
lock around the if() statement. Otherwise, "e" could be set to null
between the time you check it and the time you use it.

For example:

private void run() {
while (!disposed) {
execute handler = e;

if (handler != null) {
handler();
}
}
}

Pete
 
P

Paul Schwann

Hi Jon,

thanks a lot for input! I think, I understand most of what you and the
document you mentioned said. I have modified my little example like
this:

public class ThreadManager {
private readonly Object mutex = new Object();

private bool disposed;

public delegate void execute();

private execute executeThis;

public event execute e {
add {
lock (mutex) {
executeThis += value;
}
}
remove {
lock (mutex) {
executeThis -= value;
}
}
}

public ThreadManager() {
disposed = false;
System.Threading.Thread t = new
System.Threading.Thread(run);
t.Start();
}

private void run() {
execute copyOfExecuteThis;

while (!disposed) {
lock (mutex) {
copyOfExecuteThis = executeThis;
}

if (copyOfExecuteThis != null) {
copyOfExecuteThis();
}
}
}

public void dispose() {
disposed = true;
}
}

Only the ThreadManager class is changed. A mutex is used now to
synchronize the access from inside and outside of the class to the
delegate. The actual call to the delegate is not done on the original
but on a copy of it.

Thanks once more!

Regards,
Paul
 

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