Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3393886
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T04:06:16+00:00 2026-05-18T04:06:16+00:00

I was trying to develop a method pipeline using asynchronous method invocation. The logic

  • 0

I was trying to develop a method pipeline using asynchronous method invocation. The logic for the pipeline is as follows

  1. There are n data in a collection that have to be fed into m number of methods in a pipeline
  2. Enumerate a collection of T
  3. Feed the first element to the first method
  4. Get the output, feed it to the second method asynchronously
  5. At the same time, feed the second element of the collection to the first method
  6. After completion of the first method, fed the result to the second method (if the second method is still running, put the result into its queue and start executing the third element at first method)
  7. When second method finishes executing take the first element from the queue and execute and so on (every method should run asynchronously, no one should wait for the next to finish)
  8. At the mth method, after executing the data, store the result to a list
  9. After completing nth element at the mth method return the list of the results (n number of results) to the very first level.

I came up with a code as follows, but it did not work as intended, the result never gets returned and moreover it is not executing in the order as it should be.

static class Program
    {
        static void Main(string[] args)
        {
            var list = new List<int> { 1, 2, 3, 4 };
            var result = list.ForEachPipeline(Add, Square, Add, Square);
            foreach (var element in result)
            {
                Console.WriteLine(element);
                Console.WriteLine("---------------------");
            }
            Console.ReadLine();
        }

        private static int Add(int j)
        {
            return j + 1;
        }

        private static int Square(int j)
        {
            return j * j;
        }

        internal static void AddNotify<T>(this List<T> list, T item)
        {
            Console.WriteLine("Adding {0} to the list", item);
            list.Add(item);
        }    
    }

    internal class Function<T>
    {
        private readonly Func<T, T> _func;

        private readonly List<T> _result = new List<T>();
        private readonly Queue<T> DataQueue = new Queue<T>();
        private bool _isBusy;
        static readonly object Sync = new object();
        readonly ManualResetEvent _waitHandle = new ManualResetEvent(false);

        internal Function(Func<T, T> func)
        {
            _func = func;
        }

        internal Function<T> Next { get; set; }
        internal Function<T> Start { get; set; }
        internal int Count;

        internal IEnumerable<T> Execute(IEnumerable<T> source)
        {
            var isSingle = true;
            foreach (var element in source) {
                var result = _func(element);
                if (Next != null)
                {
                    Next.ExecuteAsync(result, _waitHandle);
                    isSingle = false;
                }
                else
                    _result.AddNotify(result);
            }
            if (!isSingle)
                _waitHandle.WaitOne();
            return _result;
        }


        internal void ExecuteAsync(T element, ManualResetEvent resetEvent)
        {
            lock(Sync)
            {
                if(_isBusy)
                {
                    DataQueue.Enqueue(element);
                    return;
                }
                _isBusy = true;

                _func.BeginInvoke(element, CallBack, resetEvent);
            }           
        }

        internal void CallBack(IAsyncResult result)
        {
            bool set = false;
            var worker = (Func<T, T>) ((AsyncResult) result).AsyncDelegate;
            var resultElement = worker.EndInvoke(result);
            var resetEvent = result.AsyncState as ManualResetEvent;

            lock(Sync)
            {
                _isBusy = false;
                if(Next != null)
                    Next.ExecuteAsync(resultElement, resetEvent);
                else
                    Start._result.AddNotify(resultElement);

                if(DataQueue.Count > 1)
                {
                    var element = DataQueue.Dequeue();
                    ExecuteAsync(element, resetEvent);
                }
                if(Start._result.Count == Count)
                    set = true;
            }
            if(set)
              resetEvent.Set();
        }
    }

    public static class Pipe
    {
        public static IEnumerable<T> ForEachPipeline<T>(this IEnumerable<T> source, params Func<T, T>[] pipes)
        {
            Function<T> start = null, previous = null;
            foreach (var function in pipes.Select(pipe => new Function<T>(pipe){ Count = source.Count()}))
            {
                if (start == null)
                {
                    start = previous = function;
                    start.Start = function;
                    continue;
                }
                function.Start = start;
                previous.Next = function;
                previous = function;
            }
            return start != null ? start.Execute(source) : null;
        }
    }

Can you guys please help me to make this thing work? If this design is not good for an actual method pipeline, please feel free to suggest a different one.

Edit: I have to stick to .Net 3.5 strictly.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T04:06:16+00:00Added an answer on May 18, 2026 at 4:06 am

    I didn’t immediately find the problem in your code, but you might be overcomplicating things a bit. This might be a simpler way to do what you want.

    public static class Pipe 
    {
       public static IEnumerable<T> Execute<T>(
          this IEnumerable<T> input, params Func<T, T>[] functions)
       {
          // each worker will put its result in this array
          var results = new T[input.Count()];
    
          // launch workers and return a WaitHandle for each one
          var waitHandles = input.Select(
             (element, index) =>
             {
                var waitHandle = new ManualResetEvent(false);
                ThreadPool.QueueUserWorkItem(
                   delegate
                   {
                      T result = element;
                      foreach (var function in functions)
                      {
                         result = function(result);
                      }
                      results[index] = result;
                      waitHandle.Set();
                   });
                return waitHandle;
             });
    
          // wait for each worker to finish
          foreach (var waitHandle in waitHandles)
          {
              waitHandle.WaitOne();
          }
          return results;
       }
    }
    

    This does not create a lock for each stage of the pipeline as in your own attempt. I’ve omitted that because it did not seem useful. However, you could easily add it by wrapping the functions like this:

    var wrappedFunctions = functions.Select(x => AddStageLock(x));
    

    where AddStageLock is this:

    private static Func<T,T> AddStageLock<T>(Func<T,T> function)
    {
       object stageLock = new object();
       Func<T, T> wrappedFunction =
          x =>
          {
             lock (stageLock)
             {
                return function(x);
             }
          };
       return wrappedFunction;
    }
    

    edit: The Execute implementation will probably be slower than single threaded execution, unless the work to be done for each individual element dwarfs the overhead of creating a wait handle and scheduling a task on the thread pool, To really benefit from multi-threading you need to limit the overhead; PLINQ in .NET 4 does this by partitioning the data.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.