示例#1
0
        public IAsync Receive(Action <Result> handler)
        {
            IAsyncSource source = Async.NewSource();
            bool         flag   = false;
            object       sync   = this.sync;

            lock (sync)
            {
                if (this.result != null)
                {
                    flag = true;
                }
                else
                {
                    if (this.handlers == null)
                    {
                        this.handlers = new List <Tuple <Action <Result>, IAsyncSource> >(1);
                    }
                    this.handlers.Add(Tuple.Create <Action <Result>, IAsyncSource>(handler, source));
                }
            }
            if (flag)
            {
                Result result = handler.Try <Result>(this.result);
                source.SetResult(result);
            }
            return(source.AsReceiveOnly());
        }
        public IAsync Enqueue(QueueSide qSide, Action callback)
        {
            Validate.Begin().IsNotNull <Action>(callback, "callback").IsTrue(((qSide == QueueSide.Front) || (qSide == QueueSide.Back)), "qSide is not a valid member of the QueueSide enumeration").Check();
            IAsyncSource source = Async.NewSource();

            if (this.pleaseAbort)
            {
                source.Throw(new OperationCanceledException("The work queue has shut down."));
            }
            else
            {
                object sync = this.Sync;
                lock (sync)
                {
                    Action item = delegate {
                        callback.Try().Into(source);
                    };
                    Action action2 = delegate {
                        source.Throw(new OperationCanceledException("The dispatcher has shut down."));
                    };
                    if (qSide == QueueSide.Front)
                    {
                        this.runFnQ.EnqueueFront(item);
                        this.cancelFnQ.EnqueueFront(action2);
                    }
                    else
                    {
                        this.runFnQ.Enqueue(item);
                        this.cancelFnQ.Enqueue(action2);
                    }
                    ThreadPool.QueueUserWorkItem(this.threadPoolCallback);
                }
            }
            return(source.AsReceiveOnly());
        }
        public IAsync BeginTry(Action callback)
        {
            base.VerifyAccess();
            IAsyncSource async = Async.NewSource();

            this.syncContext.Post(delegate(object _) {
                async.SetResult(callback.Try());
            });
            return(async);
        }
示例#4
0
        public AsyncPump(
            [NotNull] IAsyncSource <T> source,
            [NotNull] IAsyncTarget <T> target
            )
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }

            m_source = source;
            m_target = target;
        }
        /// <summary>Pump the content of a source into a list</summary>
        public static async Task <List <T> > PumpToListAsync <T>(this IAsyncSource <T> source, CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                ct.ThrowIfCancellationRequested();
            }

            var buffer = new Buffer <T>();

            var target = CreateTarget <T>(
                (x, _) => buffer.Add(x)
                );

            await PumpToAsync <T>(source, target, ct).ConfigureAwait(false);

            return(buffer.ToList());
        }
        public static IAsync <T> BeginEval <T>(this IAsyncWorkQueue queue, Func <T> f)
        {
            IAsyncSource <T> source = Async.NewSource <T>();

            queue.BeginTry(delegate {
                try
                {
                    Result <T> result = f.Eval <T>();
                    source.SetResult(result);
                }
                catch (Exception exception)
                {
                    source.Throw <T>(new TargetInvocationException(exception));
                }
            });
            return(source.AsReceiveOnly <T>());
        }
示例#7
0
        public IAsync BeginTry(Action callback)
        {
            IAsyncSource source = Async.NewSource();

            this.dispatcher.BeginInvoke(delegate {
                try
                {
                    Result @void = Result.Void;
                    callback();
                    source.SetResult(@void);
                }
                catch (Exception exception1)
                {
                    Result result = Result.NewError(exception1);
                    source.SetResult(result);
                }
            }, Array.Empty <object>());
            return(source.AsReceiveOnly());
        }
        public static async Task <List <TOutput> > TransformToListAsync <TInput, TOutput>(IAsyncSource <TInput> source, Func <TInput, CancellationToken, Task <TOutput> > transform, CancellationToken ct, int?maxConcurrency = null, TaskScheduler scheduler = null)
        {
            ct.ThrowIfCancellationRequested();

            using (var queue = CreateOrderPreservingAsyncBuffer <TOutput>(maxConcurrency ?? 32))
            {
                using (var pipe = CreateAsyncTransform <TInput, TOutput>(transform, queue, scheduler))
                {
                    // start the output pump
                    var output = PumpToListAsync(queue, ct);

                    // start the intput pump
                    var input = PumpToAsync(source, pipe, ct);

                    await Task.WhenAll(input, output).ConfigureAwait(false);

                    return(output.Result);
                }
            }
        }
        /// <summary>Consumes all the elements of the source, and publish them to the target, one by one and in order</summary>
        /// <param name="source">Source that produces elements asynchronously</param>
        /// <param name="target">Target that consumes elements asynchronously</param>
        /// <param name="ct">Cancellation token</param>
        /// <returns>Task that completes when all the elements of the source have been published to the target, or fails if on the first error, or the token is cancelled unexpectedly</returns>
        /// <remarks>The pump will only read one element at a time, and wait for it to be published to the target, before reading the next element.</remarks>
        public static async Task PumpToAsync <T>(this IAsyncSource <T> source, IAsyncTarget <T> target, CancellationToken ct)
        {
            ct.ThrowIfCancellationRequested();

            bool notifiedCompletion = false;
            bool notifiedError      = false;

            try
            {
                //LogPump("Starting pump");

                while (!ct.IsCancellationRequested)
                {
                    //LogPump("Waiting for next");

                    var current = await source.ReceiveAsync(ct).ConfigureAwait(false);

                    //LogPump("Received " + (current.HasValue ? "value" : current.Failed ? "error" : "completion") + ", publishing... " + current);
                    if (ct.IsCancellationRequested)
                    {
                        // REVIEW: should we notify the target?
                        // REVIEW: if the item is IDisposble, who will clean up?
                        break;
                    }

                    // push the data/error/completion on to the target, which will triage and update its state accordingly
                    await target.Publish(current, ct).ConfigureAwait(false);

                    if (current.Failed)
                    {                                 // bounce the error back to the caller
                                                      //REVIEW: SHOULD WE? We poush the error to the target, and the SAME error to the caller... who should be responsible for handling it?
                                                      // => target should know about the error (to cancel something)
                                                      // => caller should maybe also know that the pump failed unexpectedly....
                        notifiedError = true;
                        current.ThrowForNonSuccess(); // throws an exception right here
                        return;                       // should not be reached
                    }
                    else if (current.IsEmpty)
                    {                     // the source has completed, stop the pump
                                          //LogPump("Completed");
                        notifiedCompletion = true;
                        return;
                    }
                }

                // notify cancellation if it happend while we were pumping
                if (ct.IsCancellationRequested)
                {
                    //LogPump("We were cancelled!");
                    throw new OperationCanceledException(ct);
                }
            }
            catch (Exception e)
            {
                //LogPump("Failed: " + e);

                if (!notifiedCompletion && !notifiedError)
                {                 // notify the target that we crashed while fetching the next
                    try
                    {
                        //LogPump("Push error down to target: " + e.Message);
                        target.OnError(ExceptionDispatchInfo.Capture(e));
                        notifiedError = true;
                    }
                    catch (Exception x) when(!x.IsFatalError())
                    {
                        //LogPump("Failed to notify target of error: " + x.Message);
                    }
                }

                throw;
            }
            finally
            {
                if (!notifiedCompletion)
                {                 // we must be sure to complete the target if we haven't done so yet!
                    //LogPump("Notify target of completion due to unexpected conditions");
                    target.OnCompleted();
                }
                //LogPump("Stopped pump");
            }
        }
示例#10
0
 public static bool Into <T>(this Result <T> result, IAsyncSource <T> async) =>
 async.SetResult(result);
示例#11
0
 public static bool Into(this Result result, IAsyncSource async) =>
 async.SetResult(result);
示例#12
0
 public static bool ErrorInto <T, U>(this Result <T> tResult, IAsyncSource <U> source) =>
 (tResult.IsError && source.Throw <U>(tResult.Error));
示例#13
0
 public static IAsync <T> AsReceiveOnly <T>(this IAsyncSource <T> source) =>
 source;
示例#14
0
 public static IAsync AsReceiveOnly(this IAsyncSource source) =>
 source;
示例#15
0
 public static bool Throw <T>(this IAsyncSource <T> source, Exception ex) =>
 source.SetResult(Result.NewError <T>(ex));
示例#16
0
 public static bool Return <T>(this IAsyncSource <T> source, T value) =>
 source.SetResult(Result.New <T>(value));
示例#17
0
 public static bool Return(this IAsyncSource source) =>
 source.SetResult(Result.Void);