C# forum for web developers

Parallel.Invoke

Mar 12, 2012 4:18 pm
Clive Tooth

I have an array of Actions which I kick off with a Parallel Invoke...

Action[] workers = new Action[numThreads];
...
Parallel.Invoke(workers);

Can I have an array of Action<int> s which I somehow kick off with an
array of parameters?

Action<int>[] workers = new Action<int>[numThreads];
...
Parallel.Invoke(workers, arrayOfParameters); // ... or somesuch

?

TIA

Clive Tooth
Mar 12, 2012 5:45 pm
Peter Duniho
Re: Parallel.Invoke

On Mon, 12 Mar 2012 16:18:24 +0000, Clive Tooth wrote:

> I have an array of Actions which I kick off with a Parallel Invoke...
>
> Action[] workers = new Action[numThreads];
> ...
> Parallel.Invoke(workers);
>
> Can I have an array of Action<int> s which I somehow kick off with an
> array of parameters?
>
> Action<int>[] workers = new Action<int>[numThreads];
> ...
> Parallel.Invoke(workers, arrayOfParameters); // ... or somesuch

You could use Parallel.For(), capturing the array and using the For() index
to retrieve the parameter value?

For example:

int[] array = { 1, 1, 2, 3, 5, 8, 13 };
Action<int>[] actions = ...;

Parallel.For(0, array.Length - 1, i => actions[i](array[i]));

However, note that if you are constructing new Action<int> instances for
each index anyway, then you could have just embedded the correct argument
for each instance in the delegate instance itself (i.e. through variable
capturing).

Doing it in the way shown above seems like superfluous work to me.

A more maintainable design would be to have just a single delegate instance
that works according to an integer value passed in. This can either be
just an index:

Parallel.For(0, array.Length - 1, i => action(array[i]));

or the actual integer value from your original array:

Parallel.ForEach(array, i => action(i));

I think either of those approaches is significantly simpler and more
maintainable than making each delegate that you invoke actually be
different.

Pete


Mar 12, 2012 9:59 pm
Marcel Müller
Re: Parallel.Invoke

On 12.03.2012 17:18, Clive Tooth wrote:
> I have an array of Actions which I kick off with a Parallel Invoke...
>
> Action[] workers = new Action[numThreads];
> ...
> Parallel.Invoke(workers);
>
> Can I have an array of Action<int> s which I somehow kick off with an
> array of parameters?
>
> Action<int>[] workers = new Action<int>[numThreads];
> ...
> Parallel.Invoke(workers, arrayOfParameters); // ... or somesuch

Feel free to inject your parameters into the workers.

Action<int>[] workers = new Action<int>[numThreads];
...
Action[] workers2 = new Action[numThreads];
for (int i = 0; i < numThreads; ++i)
workers2[i] = () => workers[i](arrayOfParameters[i]);

Parallel.Invoke(workers2);


Marcel


Mar 12, 2012 11:14 pm
Peter Duniho
Re: Parallel.Invoke

On Mon, 12 Mar 2012 22:59:48 +0100, Marcel Müller wrote:

> On 12.03.2012 17:18, Clive Tooth wrote:
>> I have an array of Actions which I kick off with a Parallel Invoke...
>>
>> Action[] workers = new Action[numThreads];
>> ...
>> Parallel.Invoke(workers);
>>
>> Can I have an array of Action<int> s which I somehow kick off with an
>> array of parameters?
>>
>> Action<int>[] workers = new Action<int>[numThreads];
>> ...
>> Parallel.Invoke(workers, arrayOfParameters); // ... or somesuch
>
> Feel free to inject your parameters into the workers.
>
> Action<int>[] workers = new Action<int>[numThreads];
> ...
> Action[] workers2 = new Action[numThreads];
> for (int i = 0; i < numThreads; ++i)
> workers2[i] = () => workers[i](arrayOfParameters[i]);
>
> Parallel.Invoke(workers2);

Careful. The above will crash. The variable "i" that's being capture will,
by the even the first delegate invocation is attempted, have the value of
"numThreads", causing an IndexOutOfRangeException when dereferencing the
"workers" array (and would when dereferencing the "arrayOfParameters"
array, if the first exception didn't happen...or maybe it's the other way
around; I can't recall off the top of my head for sure).

If you're going to do it that way (it's equivalent to my second suggestion:
"[embed] the correct argument for each instance in the delegate instance
itself (i.e. through variable capturing)"), you need to write correct code:

for (int i = 0; i < numThreads; i++)
{
int j = i;

workers2[i] = () => workers[j](arrayOfParameters[j]);
}

Then each delegate instance captures a new "j" instance, which only ever
has a single value: the value that "i" had at the time of capture.

Pete




Previous Thread: Reading from a controller by HTTP
Next Thread: Server not receiving write() here and there

Related Forum Topics
I changed a portion of my code from serial to parallel - And it takeslonger
According to the Eqatec Profiler and my own eyes, the serial code runs
faster slightly than the parallel code. This despite confirmation that
each parallel thread is running half as many items.

The only thing I can think of is that the list they are both accessing
is locking when each...
Reading parallel port status pins with DeviceIOControl()
Hello all,

I've been writing a slot car lap counter in C# and currently
use the inpout32.dll to read the parallel port status pins
that are connected to lane sensors.

I wondered if there was a way of doing it without inpout32.dll
and found that I could get the status of some pins...
Synchronize or invoke?
Hi all

In my thread, I'd like to call an event in my main component.
I have a components, which is basically just an interface for my
thread, so the main programme can run freely. Passing data on to the
thread is not a problem, but I recall from Delphi this Synchronize.

It works by...
Threading and invoke
Hi all, another question

I use BeginInvoke for some components, custom controls, where the
thread can pass on "events" such as calculations complete. This works
well.

But I also have a saver, a plain non visible component, how do I do
the same there?
I cannot invoke anything from...
Method.invoke and TargetInvocationException
hi.

I am loading a program into memory and trying to run it (please don't
ask why or suggest something different)

Using this to do it:

http://www.codeproject.com/KB/cs/LoadExeIntoAssembly.aspx?display=PrintAll

It runs ok if I don't have a flash object on the form. If I do have
it, I...