Why does Parallel.Invoke fail to complete all the actions?
I worked on an example in the text book about parallel programming in C#. The book suggests Parallel.Invoke can replace the creation, invocation and waiting of tasks. However, I tried and found that if I use Parallel.Invoke, the tasks wouldn't finish before returning a value. But in theory, Parallel.Invoke should always wait.
The code:
private byte[] getDataForGraph(int dataSize)
{
byte[] data = new byte[dataSize];
Parallel.Invoke(
() => Task.Factory.StartNew(() => generateGraphData(data, 0, pixelWidth / 8)),
() => Task.Factory.StartNew(() => generateGraphData(data, pixelWidth / 8,
pixelWidth / 4)),
() => Task.Factory.StartNew(() => generateGraphData(data, pixelWidth / 4,
pixelWidth * 3 / 8)),
() => Task.Factory.StartNew(() => generateGraphData(data, pixelWidth * 3 / 8,
pixelWidth / 2)));
return data;
}
And the way to execute the function:
Task<byte[]> getDataTask = Task<byte[]>.Factory.Star开发者_如何学运维tNew(() => getDataForGraph(dataSize));
byte[] data = getDataTask.Result;
The private void generateGraphData(byte[] data, int partitionStart, int partitionEnd)
is a function that fills the data array, from partitionStart to partitionEnd.
If I run the program, only part of the array is filled. But if I replace the Invoke with
Task first = Task.Factory.StartNew(() => generateGraphData(data, 0, pixelWidth / 8));
Task second = Task.Factory.StartNew(() => generateGraphData(data, pixelWidth / 8, pixelWidth / 4));
Task third = Task.Factory.StartNew(() => generateGraphData(data, pixelWidth / 4, pixelWidth * 3 / 8));
Task fourth = Task.Factory.StartNew(() => generateGraphData(data, pixelWidth * 3 / 8, pixelWidth / 2));
Task.WaitAll(first, second, third, fourth);
The program runs as expected (the array is fully filled).
What may be the problem here?
Thanks in advance.
It performs the actions until they are complete. In your case, each action is to call Task.Factory.StartNew(...)
- and that has completed; however, there is no guarantee that each of thses tasks has been queued/processed yet. The difference is the WaitAll
(which you haven't called in your Parallel
example).
One option here would be to reduce this to:
Parallel.Invoke(
() => generateGraphData(data, 0, pixelWidth / 8),
() => generateGraphData(data, pixelWidth / 8, pixelWidth / 4),
() => generateGraphData(data, pixelWidth / 4, pixelWidth * 3 / 8),
() => generateGraphData(data, pixelWidth * 3 / 8, pixelWidth / 2)
);
精彩评论