Search code examples
c#callbackenumerable

Possible to turn callback calls into IEnumerable


I'm writing a wrapper around a 3rd party library, and it has a method to scan the data it manages. The method takes a callback method that it calls for each item in the data that it finds.

e.g. The method is essentially: void Scan(Action<object> callback);

I want to wrap it and expose a method like IEnumerable<object> Scan();

Is this possible without resorting to a separate thread to do the actual scan and a buffer?


Solution

  • You can do this quite simply with Reactive:

    class Program
    {
        static void Main(string[] args)
        {
            foreach (var x in CallBackToEnumerable<int>(Scan))
                Console.WriteLine(x);
        }
    
        static IEnumerable<T> CallBackToEnumerable<T>(Action<Action<T>> functionReceivingCallback)
        {
            return Observable.Create<T>(o =>
            {
                // Schedule this onto another thread, otherwise it will block:
                Scheduler.Later.Schedule(() =>
                {
                    functionReceivingCallback(o.OnNext);
                    o.OnCompleted();
                });
    
                return () => { };
            }).ToEnumerable();
        }
    
        public static void Scan(Action<int> act)
        {
            for (int i = 0; i < 100; i++)
            {
                // Delay to prove this is working asynchronously.
                Thread.Sleep(100);
                act(i);
            }
        }
    }
    

    Remember that this doesn't take care of things like cancellation, since the callback method doesn't really allow it. A proper solution would require work on the part of the external library.