コード例 #1
0
        public virtual async Task BuildAsync(IBundleBuilderContext context)
        {
            // applying transforms to items

            var itemTransformTasks = new ConcurrentQueue <Task <IBundleItemTransformContext> >();

            CancellationToken cancellationToken = context.CancellationToken;

            using (var errorCts = new CancellationTokenSource())
                using (context.UseExternalCancellationToken(errorCts.Token))
                {
                    var n = context.Bundle.Sources.Length;
                    for (var i = 0; i < n; i++)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        IBundleSourceModel source = context.Bundle.Sources[i];
                        await source.ProvideBuildItemsAsync(context, it => itemTransformTasks.Enqueue(Task.Run(async() =>
                        {
                            try { return(await ApplyItemTransformsAsync(it.ItemTransformContext, it.ItemTransforms)); }
                            catch (Exception ex) when(!(ex is OperationCanceledException))
                            {
                                errorCts.Cancel(); // stop processing other enqueued items
                                throw;
                            }
                        }, cancellationToken)));
                    }

                    // "If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state, where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks."
                    // "If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state."
                    // https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.whenall?view=netcore-3.1
                    await Task.WhenAll(itemTransformTasks);
                }

            // aggregating items

            var transformContext = new BundleTransformContext(context)
            {
                TransformedItemContexts = itemTransformTasks.Select(task => task.GetAwaiter().GetResult()).ToArray()
            };

            itemTransformTasks = null;

            await AggregateAsync(transformContext, context.Bundle.Transforms);

            // applying transforms to bundle

            transformContext.TransformedItemContexts = null;

            context.Result = await ApplyTransformsAsync(transformContext, context.Bundle.Transforms);
        }
コード例 #2
0
        public virtual async Task BuildAsync(IBundleBuilderContext context)
        {
            // building items

            CreateItemTransformPipeline(context, out ITargetBlock <IBundleSourceBuildItem> input, out ISourceBlock <IBundleItemTransformContext> output);

            // consumer
            async Task <List <IBundleItemTransformContext> > ConsumeAsync()
            {
                var itemContexts = new List <IBundleItemTransformContext>();

                while (await output.OutputAvailableAsync(context.CancellationToken))
                {
                    itemContexts.Add(output.Receive());
                }

                return(itemContexts);
            };

            Task <List <IBundleItemTransformContext> > consumeTask = ConsumeAsync();

            // producer
            var n = context.Bundle.Sources.Length;

            for (var i = 0; i < n; i++)
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                IBundleSourceModel source = context.Bundle.Sources[i];
                await source.ProvideBuildItemsAsync(context, it => input.Post(it));
            }
            input.Complete();

            // building result

            var transformContext = new BundleTransformContext(context)
            {
                TransformedItemContexts = await consumeTask
            };

            await AggregateAsync(transformContext, context.Bundle.Transforms);

            transformContext.TransformedItemContexts = null;

            context.Result = await ApplyTransformsAsync(transformContext, context.Bundle.Transforms);
        }