Start and end call in one extension method properly

I want to double check with others whether this will be the right way to create an extension method that starts the asynchronous process and returns a function that, when called, essentially waits for this process and gets the result.

    public static Func<R> HandleInvoke<T, R>(this Func<T, R> function, T arg, Action<IAsyncResult> callback)
    {
        IAsyncResult result = function.BeginInvoke(arg, new AsyncCallback(callback), function);

        return delegate
        {
            return function.EndInvoke(result);
        };
    }

Essentially, I want to use it as a pseudo (pseudo-code):

Func<R> myFunc = (some delegate).HandleInvoke(arg, callback);  
                     // at this point the operation begins, but will be nonblocking

                     // do other stuff

var result = myFunc();   // now I am deciding to wait on the result, which is blocking

Not sure if I need to worry about waiting in WaitHandles in this situation or not. Also not sure if you even need to make a callback. Also I think this is a closure?

EDIT

It ends with this

    public static Func<R> HandleInvoke<T, R>(this Func<T, R> function, T arg)
    {
        IAsyncResult asyncResult = function.BeginInvoke(arg, iAsyncResult =>
            {
                if (!(iAsyncResult as AsyncResult).EndInvokeCalled)
                {
                    (iAsyncResult.AsyncState as Func<T, R>).EndInvoke(iAsyncResult);
                }

            }, function); 

        return delegate
        {
            WaitHandle.WaitAll(new WaitHandle[] { asyncResult.AsyncWaitHandle }); 

            return function.EndInvoke(asyncResult); 
        };
    }

Which seems to work well. The callback checks if EndInvoke has been called, and if not, calls it. Otherwise, EndInvoke is called inside the returned delegate.

2ND EDIT

- , , . , .EndInvoke(), , EndInvoke R. Thread.Sleep(), , . , , R .

    public static Func<R> HandleInvoke<T, R>(this Func<T, R> function, T arg)
    {
        R r = default(R); 

        IAsyncResult asyncResult = function.BeginInvoke(arg, result =>
            {
                r = (result.AsyncState as Func<T, R>).EndInvoke(result);

            }, function); 


        return delegate
        {
            while (!(asyncResult as AsyncResult).EndInvokeCalled)
            {
                Thread.Sleep(1); 
            }

            return r; 
        };
    }
+3
2

, ... .

myFunc , EndInvoke , myFunc , , EndInvoke. API .

, , , . , , . ,

    public static Func<R> HandleInvoke<T, R>(this Func<T, R> function, T arg)
    {
        R retv = default(R);
        bool completed = false;

        object sync = new object();

        IAsyncResult asyncResult = function.BeginInvoke(arg, 
            iAsyncResult =>
            {
                lock(sync)
                {
                    completed = true;
                    retv = function.EndInvoke(iAsyncResult);
                    Monitor.Pulse(sync); // wake a waiting thread is there is one
                }
            }
            , null);

        return delegate
        {

            lock (sync)
            {
                if (!completed) // if not called before the callback completed
                {
                    Monitor.Wait(sync); // wait for it to pulse the sync object
                }
                return retv;
            }
        };
    }
+2

, (re) , :

    public static Func<R> Future<T, R>(this Func<T, R> func, T arg)
    {
        IAsyncResult result = func.BeginInvoke(arg, null, null);

        return () => func.EndInvoke(result);
    }

Action:

    public static Action Future<T>(this Action<T> action, T arg)
    {
        IAsyncResult result = action.BeginInvoke(arg, null, null);

        return () => action.EndInvoke(result);
    }

, ThreadPool.QueueUserWorkItem() .

+1

All Articles