Example #1
0
        /// <summary>
        /// Runs code within a new loader context before firing any pending
        /// <see cref="DataLoader{TKey,TReturn}">DataLoader</see> instances.
        /// </summary>
        public static Task <T> Run <T>(Func <DataLoaderContext, Task <T> > func)
        {
            if (func == null)
            {
                throw new ArgumentNullException(nameof(func));
            }

            // TODO: Investigate this.
            //
            // For some reason, using `Task.Run` causes <see cref="TaskCompletionSource{T}"/> to run continuations
            // synchronously, which prevents the main loop from continuing on to the next loader before they're done.
            //
            // I presume this is because once we're inside the ThreadPool, continuations will be scheduled using the
            // local queues (in LIFO order) instead of the global queue (which executes in FIFO order). This is really
            // a hack I think - the same thing should be accomplished using a custom TaskScheduler or custom awaiter.
            return(Task.Run <T>(() =>
            {
                using (var scope = new DataLoaderScope())
                {
                    var task = func(scope.Context);
                    if (task == null)
                    {
                        throw new InvalidOperationException("No task provided.");
                    }
                    return task;
                }
            }));
        }
Example #2
0
        /// <summary>
        /// Runs code within a new loader context before firing any pending
        /// <see cref="DataLoader{TKey,TReturn}">DataLoader</see> instances.
        /// </summary>
        public static Task Run(Func <DataLoaderContext, Task> func)
        {
            if (func == null)
            {
                throw new ArgumentNullException(nameof(func));
            }

            // TODO: see above
            return(Task.Run(() =>
            {
                using (var scope = new DataLoaderScope())
                {
                    var task = func(scope.Context);
                    if (task == null)
                    {
                        throw new InvalidOperationException("No task provided.");
                    }
                    return task;
                }
            }));
        }