I have several counters that list flatter files. Initially, I had every enumerator in the Parallel Invoke, and each action added to the BlockingCollection<Entity> and that the collections returned the value ConsumingEnumerable ();
public interface IFlatFileQuery { IEnumerable<Entity> Run(); } public class FlatFile1 : IFlatFileQuery { public IEnumerable<Entity> Run() { // loop over a flat file and yield each result yield return Entity; } } public class Main { public IEnumerable<Entity> DoLongTask(ICollection<IFlatFileQuery> _flatFileQueries) { // do some other stuff that needs to be returned first: yield return Entity; // then enumerate and return the flat file data foreach (var entity in GetData(_flatFileQueries)) { yield return entity; } } private IEnumerable<Entity> GetData(_flatFileQueries) { var buffer = new BlockingCollection<Entity>(100); var actions = _flatFileQueries.Select(fundFileQuery => (Action)(() => { foreach (var entity in fundFileQuery.Run()) { buffer.TryAdd(entity, Timeout.Infinite); } })).ToArray(); Task.Factory.StartNew(() => { Parallel.Invoke(actions); buffer.CompleteAdding(); }); return buffer.GetConsumingEnumerable(); } }
However, after a little testing, it turns out that changing the code below is 20-25% faster.
private IEnumerable<Entity> GetData(_flatFileQueries) { return _flatFileQueries.AsParallel().SelectMany(ffq => ffq.Run()); }
The problem with changing the code is that it waits until all requests with a flat file are listed before it returns the entire batch, which can then be listed and provided.
Is it possible to concede in the above bit of code to somehow make it even faster?
I must add that, at a minimum, the combined results of all flat queries can only be 1000 or so.
Edit : Changing it to the following does not affect the execution time. (R # even suggests getting back to how it was)
private IEnumerable<Entity> GetData(_flatFileQueries) { foreach (var entity in _flatFileQueries.AsParallel().SelectMany(ffq => ffq.Run())) { yield return entity; } }
Mark vickery
source share