Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 853
Gareth Avatar asked Feb 10 '11 10:02

Gareth


2 Answers

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.

like image 181
porges Avatar answered Sep 24 '22 18:09

porges


You should investigate the Rx project — this allows an event source to be consumed as an IEnumerable.

I'm not sure if it allows vanilla callbacks to be presented as such (it's aimed at .NET events) but it would be worth a look as it should be possible to present a regular callback as an IObservable.

like image 32
Paul Ruane Avatar answered Sep 23 '22 18:09

Paul Ruane