Mar 12, 2012 4:18 pm
Clive ToothI 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 DunihoOn 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
>
> 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üllerOn 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
>
> 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 DunihoOn Mon, 12 Mar 2012 22:59:48 +0100, Marcel Müller wrote:
> On 12.03.2012 17:18, Clive Tooth wrote:
> 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);
>> 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
> >>
>> 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