public void Test_MonadLaw() { // return x >>= f == f x // m >>= return == m // (m >>= f) >>= g == m >>= (\x -> f x >>= g) { // return x >>= f == f x Func <int, MaybeTask <int> > func = i => MaybeTask.Return(DummyTask(i)); var result1 = func(10); var result2 = MaybeTask.Return(DummyTask(10)).Bind(func); Assert.Equal(result1.Awaitor.Result, result2.Awaitor.Result); } { // m >>= return == m var result1 = MaybeTask.Return(DummyTask(10)); var result2 = result1.Bind(i => MaybeTask.Return(DummyTask(i))); Assert.Equal(result1.Awaitor.Result, result2.Awaitor.Result); } { // (m >>= f) >>= g == m >>= (\x -> f x >>= g) Func <int, MaybeTask <int> > f = i => MaybeTask.Return(DummyTask(i + 1)); Func <int, MaybeTask <int> > g = i => MaybeTask.Return(DummyTask(i + 10)); var m = MaybeTask.Return(DummyTask(10)); var result1 = m.Bind(f).Bind(g); var result2 = m.Bind(i => f(i).Bind(g)); Assert.Equal(result1.Awaitor.Result, result2.Awaitor.Result); } }
internal static MaybeTask <IImageProvider> Bind(MaybeTask <IImageProvider> currentImage, MaybeTask <IImageProvider> previousImage) { // Note: the code below is written with static lambdas that don't close over any variables. This avoids heap allocations. if (currentImage.IsSynchronous) { if (previousImage.IsSynchronous) { return(new MaybeTask <IImageProvider>(Bind(currentImage.Result, previousImage.Result))); } else // previousImage.IsAsynchronous { return(new MaybeTask <IImageProvider>(previousImage.Task.ContinueWith(BindPreviousAsyncToCurrentSync, currentImage.Result, ContinuationOptions))); } } else // currentImage.IsAsynchronous { if (previousImage.IsSynchronous) { return(new MaybeTask <IImageProvider>(currentImage.Task.ContinueWith(BindPreviousSyncToCurrentAsync, previousImage.Result, ContinuationOptions))); } else // previousImage.IsAsynchronous { return(new MaybeTask <IImageProvider>(currentImage.Task.ContinueWith(BindPreviousAsyncToCurrentAsync, previousImage.Task, ContinuationOptions).Unwrap())); } } }
internal static MaybeTask<IImageProvider> Bind(MaybeTask<IImageProvider> currentImage, MaybeTask<IImageProvider> previousImage) { // Note: the code below is written with static lambdas that don't close over any variables. This avoids heap allocations. if (currentImage.IsSynchronous) { if (previousImage.IsSynchronous) { return new MaybeTask<IImageProvider>(Bind(currentImage.Result, previousImage.Result)); } else // previousImage.IsAsynchronous { return new MaybeTask<IImageProvider>(previousImage.Task.ContinueWith(BindPreviousAsyncToCurrentSync, currentImage.Result, ContinuationOptions)); } } else // currentImage.IsAsynchronous { if (previousImage.IsSynchronous) { return new MaybeTask<IImageProvider>(currentImage.Task.ContinueWith(BindPreviousSyncToCurrentAsync, previousImage.Result, ContinuationOptions)); } else // previousImage.IsAsynchronous { return new MaybeTask<IImageProvider>(currentImage.Task.ContinueWith(BindPreviousAsyncToCurrentAsync, previousImage.Task, ContinuationOptions).Unwrap()); } } }
public void Test_Awaitor1() { // 単一Task var state = MaybeTask.From(DummyTask(10)); var result = state.Awaitor.Result; Assert.True(result.HasValue); Assert.Equal(10, Polluter.Pollute(result)); }
public void Test_Nothing() { // Nothingを返すTaskはNothingになる var state = MaybeTask .From(NothingTask()); var result = state.Awaitor.Result; Assert.False(result.HasValue); }
public void MaybeTaskRepresentsResult() { object o = new object(); var mt = new MaybeTask<object>(o); Assert.IsTrue(mt.WasSynchronous); Assert.IsTrue(mt.IsSynchronous); Assert.IsFalse(mt.IsEmpty); Assert.IsNull(mt.Task); Assert.AreEqual(o, mt.Result); }
public void MaybeTaskRepresentsAlreadyCompletedTask() { object o = new object(); var mt = new MaybeTask<object>(Task.FromResult(o)); Assert.IsFalse(mt.WasSynchronous); Assert.IsTrue(mt.IsSynchronous); // result is available now Assert.IsFalse(mt.IsEmpty); Assert.IsNotNull(mt.Task); Assert.AreEqual(o, mt.Result); }
public void Test_Nothing2() { // NothingをかえすTaskがある場合はNothingになる。 var state = MaybeTask .From(DummyTask(10)) .Map(NothingTask()); var result = state.Awaitor.Result; Assert.False(result.HasValue); }
public void MaybeTaskRepresentsAlreadyCompletedTask() { object o = new object(); var mt = new MaybeTask <object>(Task.FromResult(o)); Assert.IsFalse(mt.WasSynchronous); Assert.IsTrue(mt.IsSynchronous); // result is available now Assert.IsFalse(mt.IsEmpty); Assert.IsNotNull(mt.Task); Assert.AreEqual(o, mt.Result); }
public void MaybeTaskRepresentsResult() { object o = new object(); var mt = new MaybeTask <object>(o); Assert.IsTrue(mt.WasSynchronous); Assert.IsTrue(mt.IsSynchronous); Assert.IsFalse(mt.IsEmpty); Assert.IsNull(mt.Task); Assert.AreEqual(o, mt.Result); }
public void Test_Awaitor2() { // 2つのTaskを直列化 var state = MaybeTask .From(DummyTask(10)) .Map(DummyTask(15)); var result = state.Awaitor.Result; Assert.True(result.HasValue); Assert.Equal(10, Polluter.Pollute(result).Item1); Assert.Equal(15, Polluter.Pollute(result).Item2); }
public void MaybeTaskRepresentsAlreadyCanceledTask() { object o = new object(); var tcs = new TaskCompletionSource <object>(); tcs.SetCanceled(); var mt = new MaybeTask <object>(tcs.Task); Assert.IsFalse(mt.WasSynchronous); Assert.IsTrue(mt.IsSynchronous); Assert.IsFalse(mt.IsEmpty); Assert.IsNotNull(mt.Task); Assert.ThrowsException <AggregateException>(() => mt.Result); }
public void MaybeTaskRepresentsCancelingTask() { object o = new object(); var tcs = new TaskCompletionSource<object>(); var mt = new MaybeTask<object>(tcs.Task); Assert.IsFalse(mt.WasSynchronous); Assert.IsFalse(mt.IsSynchronous); Assert.IsFalse(mt.IsEmpty); Assert.IsNotNull(mt.Task); tcs.SetCanceled(); Assert.IsFalse(mt.WasSynchronous); Assert.IsTrue(mt.IsSynchronous); Assert.ThrowsException<AggregateException>(() => mt.Result); }
public void MaybeTaskRepresentsCompletingTask() { object o = new object(); var tcs = new TaskCompletionSource<object>(); var mt = new MaybeTask<object>(tcs.Task); Assert.IsFalse(mt.WasSynchronous); Assert.IsFalse(mt.IsSynchronous); Assert.IsFalse(mt.IsEmpty); Assert.IsNotNull(mt.Task); tcs.SetResult(o); Assert.IsFalse(mt.WasSynchronous); Assert.IsTrue(mt.IsSynchronous); Assert.AreEqual(o, mt.Result); }
public void Test_Awaitor3_Flat() { // 3つのTaskを直列化 // 結果は自身で定義する。 var state = MaybeTask .From(DummyTask(10)) .Map(async prev => (await DummyTask(15)).Map(next => (prev, next))) .Map(async prev => (await DummyTask(20)).Map(next => (prev.Item1, prev.Item2, next))); var result = state.Awaitor.Result; Assert.True(result.HasValue); Assert.Equal(10, Polluter.Pollute(result).Item1); Assert.Equal(15, Polluter.Pollute(result).Item2); Assert.Equal(20, Polluter.Pollute(result).Item3); }
public void MaybeTaskRepresentsCompletingTask() { object o = new object(); var tcs = new TaskCompletionSource <object>(); var mt = new MaybeTask <object>(tcs.Task); Assert.IsFalse(mt.WasSynchronous); Assert.IsFalse(mt.IsSynchronous); Assert.IsFalse(mt.IsEmpty); Assert.IsNotNull(mt.Task); tcs.SetResult(o); Assert.IsFalse(mt.WasSynchronous); Assert.IsTrue(mt.IsSynchronous); Assert.AreEqual(o, mt.Result); }
public void Test_Awaitor3() { // 3つのTaskを直列化。 // 結果はTuple<Tuple<1, 2>, 3> var state = MaybeTask .From(DummyTask(10)) .Map(DummyTask(15)) .Map(DummyTask(20)); var result = state.Awaitor.Result; Assert.True(result.HasValue); Assert.Equal(10, Polluter.Pollute(result).Item1.Item1); Assert.Equal(15, Polluter.Pollute(result).Item1.Item2); Assert.Equal(20, Polluter.Pollute(result).Item2); }
/// <summary> /// Construct a layer style. /// </summary> /// <param name="blendFunction">Blend function to use when combining the result of this layer with the previous.</param> /// <param name="opacity">The opacity of the layer.</param> /// <param name="maskImage">If non-null, specifies a mask image that controls how this layer is blended onto the preceding one. See <see cref="Lumia.Imaging.Compositing.BlendEffect"/>.</param> /// <param name="targetArea">If non-empty, positions and scales the layer within the bounds of the preceding one. See <see cref="Lumia.Imaging.Compositing.BlendEffect"/>.</param> /// <returns>A layer style.</returns> public LayerStyle(BlendFunction blendFunction, double opacity, MaybeTask <IImageProvider> maskImage, Rect?targetArea = null) { BlendFunction = blendFunction; Opacity = opacity; TargetArea = targetArea; if (!maskImage.IsEmpty) { MaskResolver = context => maskImage; } else { MaskResolver = null; } }
private Layer GetActiveBackgroundLayer(MaybeTask <IImageProvider> backgroundImage, Size backgroundImageSize) { var backgroundLayer = this[0]; // Replace BG layer? if (!backgroundImage.IsEmpty) { if (backgroundLayer != EmptyLayer) { throw new ArgumentException("LayerList was constructed with a background image, do not pass one into ToImageProvider.", "backgroundImage"); } backgroundLayer = new Layer(LayerStyle.Normal(), backgroundImage, backgroundImageSize); } return(backgroundLayer); }
public void Test_Awaitor3_Flat2() { // 3つのTaskを直列化 // 結果は自身で定義する。 // Maybe a -> (a -> Task<Maybe (a b)>) -> Maybe (a b)は実装がわかりにくいので自動化 // Maybe a -> (a -> Task<(a Maybe b)>) -> (a Maybe b)とならないように。 var state = MaybeTask .From(DummyTask(10)) .Map(prev => DummyTask(15), (prev, next) => Optional.Just((prev, next))) .Map(prev => DummyTask(20), (prev, next) => Optional.Just((prev.Item1, prev.Item2, next))); var result = state.Awaitor.Result; Assert.True(result.HasValue); Assert.Equal(10, Polluter.Pollute(result).Item1); Assert.Equal(15, Polluter.Pollute(result).Item2); Assert.Equal(20, Polluter.Pollute(result).Item3); }
public void Test_Nothing3() { bool called1 = false; bool called2 = false; // NothingをかえすTaskがある場合はNothingになる。 // ※Nothingの前のTaskを返却する関数は実行される。 // ※Nothingの後のTaskを返却する関数は実行されない。 var state = MaybeTask .From(DummyTask(10)) .Map(prev => CallbackTask(() => { called1 = true; return(1); })) .Map(NothingTask()) .Map(prev => CallbackTask(() => { called2 = true; return(1); })); var result = state.Awaitor.Result; Assert.False(result.HasValue); Assert.True(called1); Assert.False(called2); }
/// <summary> /// Resolve a MaybeTask<IImageProvider> that represents the whole layer stack. /// </summary> /// <param name="backgroundImage">A MaybeTask<IImageProvider> resulting in the image to use for the background layer.</param> /// <param name="backgroundImageSize">Optionally, the size of the background image. If omitted, the natural size of the source will be used, but the size will not available in the LayerLinkingContext for lazy resolvers.</param> /// <param name="renderSizeHint">Optionally, the size of image that the layer stack will be rendered to. Note that this is just a hint, the resulting <see cref="IImageProvider" /> should also be rendered at this size by the user.</param> /// <returns>An IImageProvider that represents the whole layer stack.</returns> public MaybeTask <IImageProvider> ToImageProvider(MaybeTask <IImageProvider> backgroundImage, Size backgroundImageSize = default(Size), Size renderSizeHint = default(Size)) { var backgroundLayer = GetActiveBackgroundLayer(backgroundImage, backgroundImageSize); var layerContextInvariants = new LayerContext.Invariants(backgroundLayer, backgroundImage, renderSizeHint); var layerContexts = new LayerContext[Count]; layerContexts[0] = new LayerContext(layerContextInvariants, null, backgroundLayer, 0); backgroundImage = backgroundLayer.GetImageProvider(layerContexts[0]); var currentImage = backgroundImage; for (int layerIndex = 1; layerIndex < layerContexts.Length; ++layerIndex) { Debug.WriteLine("Resolving layer " + layerIndex); var context = new LayerContext(layerContextInvariants, layerContexts[layerIndex - 1].CurrentLayer, this[layerIndex], layerIndex); context.PreviousImage = currentImage; currentImage = context.CurrentLayer.GetImageProvider(context); Debug.Assert(!currentImage.IsEmpty, "Resolved imageprovider is null."); // Bind the previous image as the source of the current one. currentImage = LayerSource.Bind(currentImage, context.PreviousImage); // If blending is used, wrap the current image in a BlendEffect and bind the source to it as well. var blendedCurrentImage = LayerBlend.Apply(context, currentImage); if (!blendedCurrentImage.IsEmpty) { blendedCurrentImage = LayerSource.Bind(blendedCurrentImage, context.PreviousImage); currentImage = blendedCurrentImage; } layerContexts[layerIndex] = context; } Debug.WriteLine("Resolved final image provider."); return(currentImage); }
internal static MaybeTask <IImageProvider> Apply(LayerContext context, MaybeTask <IImageProvider> image) { var layer = context.CurrentLayer; var mask = new MaybeTask <IImageProvider>(); if (layer.Style.MaskResolver != null) { mask = layer.Style.MaskResolver(context); } const double opacityEpsilon = 0.01; bool isOpaque = context.CurrentLayerIndex == 0 || ((layer is AdjustmentLayer) && layer.Style.BlendFunction == BlendFunction.Normal && Math.Abs(layer.Style.Opacity - 1.0) <= opacityEpsilon); if (isOpaque) { return(new MaybeTask <IImageProvider>()); } // This whole unfolded mess may look silly, but allows us to do the bare minimum. // It defers resolving task-ness until later, so there are less objects allocated on average. // Using async/await causes quite a few extra objects on the heap. // We also try to avoid Task.FromResult which is at least one extra Task on the heap. // Task.WhenAll is not efficient in .NET 4.0, and it's unknown how that translates to Silverlight for WP 8.0. var blendParams = new BlendParams { PreviousImage = context.PreviousImage, Image = image, Mask = mask, Style = layer.Style }; if (blendParams.PreviousImage.IsSynchronous) { if (blendParams.Image.IsSynchronous) { if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty) { return(new MaybeTask <IImageProvider>(CreateBlendEffect(blendParams))); } else { return(new MaybeTask <IImageProvider>( mask.Task.ContinueWith((maskTask, state) => { var bp = (BlendParams)state; bp.Mask = new MaybeTask <IImageProvider>(maskTask.Result); return CreateBlendEffect(bp); }, blendParams, ContinuationOptions))); } } else // image.IsAsynchronous { if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty) { return(new MaybeTask <IImageProvider>( image.Task.ContinueWith((imageTask, state) => { var bp = (BlendParams)state; bp.Image = new MaybeTask <IImageProvider>(imageTask.Result); return CreateBlendEffect(bp); }, blendParams, ContinuationOptions))); } else // mask.IsAsynchronous { return(new MaybeTask <IImageProvider>( image.Task.ContinueWith((imageTask, state) => { var bp = (BlendParams)state; bp.Image = new MaybeTask <IImageProvider>(imageTask.Result); return bp.Mask.Task.ContinueWith((maskTask, state2) => { var bp2 = (BlendParams)state2; bp2.Mask = new MaybeTask <IImageProvider>(maskTask.Result); return CreateBlendEffect(bp2); }, bp, ContinuationOptions); }, blendParams, ContinuationOptions).Unwrap())); } } } else // previousImage.IsAsynchronous { if (blendParams.Image.IsSynchronous) { if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty) { return(new MaybeTask <IImageProvider>( blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) => { var bp = (BlendParams)state; bp.PreviousImage = new MaybeTask <IImageProvider>(previousImageTask.Result); return CreateBlendEffect(bp); }, blendParams, ContinuationOptions))); } else // mask.IsAsynchronous { return(new MaybeTask <IImageProvider>( blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state2) => { var blendParams2 = (BlendParams)state2; blendParams2.PreviousImage = new MaybeTask <IImageProvider>(previousImageTask.Result); return blendParams2.Mask.Task.ContinueWith((maskTask, state3) => { var blendParams3 = (BlendParams)state3; blendParams3.Mask = new MaybeTask <IImageProvider>(maskTask.Result); return CreateBlendEffect(blendParams3); }, blendParams2, ContinuationOptions); }, blendParams, ContinuationOptions).Unwrap())); } } else // image.IsAsynchronous { if (mask.IsSynchronous || mask.IsEmpty) { return(new MaybeTask <IImageProvider>( blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) => { var bp = (BlendParams)state; bp.PreviousImage = new MaybeTask <IImageProvider>(previousImageTask.Result); return bp.Image.Task.ContinueWith((imageTask, state2) => { var bp2 = (BlendParams)state2; bp2.Image = new MaybeTask <IImageProvider>(imageTask.Result); return CreateBlendEffect(bp2); }, bp, ContinuationOptions); }, blendParams, ContinuationOptions).Unwrap())); } else // mask.IsAsynchronous { return(new MaybeTask <IImageProvider>( blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) => { var bp = (BlendParams)state; bp.PreviousImage = new MaybeTask <IImageProvider>(previousImageTask.Result); return bp.Image.Task.ContinueWith((imageTask, state2) => { var bp2 = (BlendParams)state2; bp2.Image = new MaybeTask <IImageProvider>(imageTask.Result); return bp2.Mask.Task.ContinueWith((maskTask, state3) => { var bp3 = (BlendParams)state3; bp3.Mask = new MaybeTask <IImageProvider>(maskTask.Result); return CreateBlendEffect(bp3); }, bp2, ContinuationOptions); }, bp, ContinuationOptions); }, blendParams, ContinuationOptions).Unwrap().Unwrap())); } } } throw new NotImplementedException(); }
/// <summary> /// Construct a layer style. /// </summary> /// <param name="blendFunction">Blend function to use when combining the result of this layer with the previous.</param> /// <param name="opacity">The opacity of the layer.</param> /// <param name="maskImage">If non-null, specifies a mask image that controls how this layer is blended onto the preceding one. See <see cref="Lumia.Imaging.Compositing.BlendEffect"/>.</param> /// <param name="targetArea">If non-empty, positions and scales the layer within the bounds of the preceding one. See <see cref="Lumia.Imaging.Compositing.BlendEffect"/>.</param> /// <returns>A layer style.</returns> public LayerStyle(BlendFunction blendFunction, double opacity, MaybeTask<IImageProvider> maskImage, Rect? targetArea = null) { BlendFunction = blendFunction; Opacity = opacity; TargetArea = targetArea; if (!maskImage.IsEmpty) { MaskResolver = context => maskImage; } else { MaskResolver = null; } }
/// <summary> /// Creates a layer with image content. /// </summary> /// <param name="layerStyle">Description of how to blend this layer onto the preceding one.</param> /// <param name="imageProvider">A value that represents either the <see cref="IImageProvider" /> that is the image content or a task that asynchronously results in it.</param> /// <param name="imageSize">Optional, the size of the image content of the layer.</param> public Layer(LayerStyle layerStyle, MaybeTask <IImageProvider> imageProvider, Size imageSize = default(Size)) { Style = layerStyle; GetImageProvider = context => imageProvider; ImageSize = imageSize; }
/// <summary> /// Creates an adjustment layer containing the specified effect. /// </summary> /// <param name="layerStyle">Layer style to use for this layer.</param> /// <param name="effectTask">An already started task that asynchronously results in the effect to apply in the adjustment layer.</param> /// <returns>The adjustment layer.</returns> public AdjustmentLayer(LayerStyle layerStyle, MaybeTask<IImageProvider> effectTask) : base(layerStyle, effectTask, Size.Empty) { }
/// <summary> /// Creates an adjustment layer containing the specified effect. /// </summary> /// <param name="layerStyle">Layer style to use for this layer.</param> /// <param name="effectTask">An already started task that asynchronously results in the effect to apply in the adjustment layer.</param> /// <returns>The adjustment layer.</returns> public AdjustmentLayer(LayerStyle layerStyle, MaybeTask <IImageProvider> effectTask) : base(layerStyle, effectTask, Size.Empty) { }
internal Invariants(Layer backgroundLayer, MaybeTask <IImageProvider> backgroundImage, Size renderSizeHint) { BackgroundLayer = backgroundLayer; BackgroundImage = backgroundImage; HintedRenderSize = renderSizeHint; }
/// <summary> /// Creates a layer with image content. /// </summary> /// <param name="layerStyle">Description of how to blend this layer onto the preceding one.</param> /// <param name="imageProvider">A value that represents either the <see cref="IImageProvider" /> that is the image content or a task that asynchronously results in it.</param> /// <param name="imageSize">Optional, the size of the image content of the layer.</param> public Layer(LayerStyle layerStyle, MaybeTask<IImageProvider> imageProvider, Size imageSize = default(Size)) { Style = layerStyle; GetImageProvider = context => imageProvider; ImageSize = imageSize; }
internal Invariants(Layer backgroundLayer, MaybeTask<IImageProvider> backgroundImage, Size renderSizeHint) { BackgroundLayer = backgroundLayer; BackgroundImage = backgroundImage; HintedRenderSize = renderSizeHint; }
internal static MaybeTask<IImageProvider> Apply(LayerContext context, MaybeTask<IImageProvider> image) { var layer = context.CurrentLayer; var mask = new MaybeTask<IImageProvider>(); if (layer.Style.MaskResolver != null) { mask = layer.Style.MaskResolver(context); } const double opacityEpsilon = 0.01; bool isOpaque = context.CurrentLayerIndex == 0 || ((layer is AdjustmentLayer) && layer.Style.BlendFunction == BlendFunction.Normal && Math.Abs(layer.Style.Opacity - 1.0) <= opacityEpsilon); if (isOpaque) { return new MaybeTask<IImageProvider>(); } // This whole unfolded mess may look silly, but allows us to do the bare minimum. // It defers resolving task-ness until later, so there are less objects allocated on average. // Using async/await causes quite a few extra objects on the heap. // We also try to avoid Task.FromResult which is at least one extra Task on the heap. // Task.WhenAll is not efficient in .NET 4.0, and it's unknown how that translates to Silverlight for WP 8.0. var blendParams = new BlendParams { PreviousImage = context.PreviousImage, Image = image, Mask = mask, Style = layer.Style }; if (blendParams.PreviousImage.IsSynchronous) { if (blendParams.Image.IsSynchronous) { if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty) { return new MaybeTask<IImageProvider>(CreateBlendEffect(blendParams)); } else { return new MaybeTask<IImageProvider>( mask.Task.ContinueWith((maskTask, state) => { var bp = (BlendParams)state; bp.Mask = new MaybeTask<IImageProvider>(maskTask.Result); return CreateBlendEffect(bp); }, blendParams, ContinuationOptions)); } } else // image.IsAsynchronous { if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty) { return new MaybeTask<IImageProvider>( image.Task.ContinueWith((imageTask, state) => { var bp = (BlendParams)state; bp.Image = new MaybeTask<IImageProvider>(imageTask.Result); return CreateBlendEffect(bp); }, blendParams, ContinuationOptions)); } else // mask.IsAsynchronous { return new MaybeTask<IImageProvider>( image.Task.ContinueWith((imageTask, state) => { var bp = (BlendParams)state; bp.Image = new MaybeTask<IImageProvider>(imageTask.Result); return bp.Mask.Task.ContinueWith((maskTask, state2) => { var bp2 = (BlendParams)state2; bp2.Mask = new MaybeTask<IImageProvider>(maskTask.Result); return CreateBlendEffect(bp2); }, bp, ContinuationOptions); }, blendParams, ContinuationOptions).Unwrap()); } } } else // previousImage.IsAsynchronous { if (blendParams.Image.IsSynchronous) { if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty) { return new MaybeTask<IImageProvider>( blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) => { var bp = (BlendParams)state; bp.PreviousImage = new MaybeTask<IImageProvider>(previousImageTask.Result); return CreateBlendEffect(bp); }, blendParams, ContinuationOptions)); } else // mask.IsAsynchronous { return new MaybeTask<IImageProvider>( blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state2) => { var blendParams2 = (BlendParams)state2; blendParams2.PreviousImage = new MaybeTask<IImageProvider>(previousImageTask.Result); return blendParams2.Mask.Task.ContinueWith((maskTask, state3) => { var blendParams3 = (BlendParams)state3; blendParams3.Mask = new MaybeTask<IImageProvider>(maskTask.Result); return CreateBlendEffect(blendParams3); }, blendParams2, ContinuationOptions); }, blendParams, ContinuationOptions).Unwrap()); } } else // image.IsAsynchronous { if (mask.IsSynchronous || mask.IsEmpty) { return new MaybeTask<IImageProvider>( blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) => { var bp = (BlendParams)state; bp.PreviousImage = new MaybeTask<IImageProvider>(previousImageTask.Result); return bp.Image.Task.ContinueWith((imageTask, state2) => { var bp2 = (BlendParams)state2; bp2.Image = new MaybeTask<IImageProvider>(imageTask.Result); return CreateBlendEffect(bp2); }, bp, ContinuationOptions); }, blendParams, ContinuationOptions).Unwrap()); } else // mask.IsAsynchronous { return new MaybeTask<IImageProvider>( blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) => { var bp = (BlendParams)state; bp.PreviousImage = new MaybeTask<IImageProvider>(previousImageTask.Result); return bp.Image.Task.ContinueWith((imageTask, state2) => { var bp2 = (BlendParams)state2; bp2.Image = new MaybeTask<IImageProvider>(imageTask.Result); return bp2.Mask.Task.ContinueWith((maskTask, state3) => { var bp3 = (BlendParams)state3; bp3.Mask = new MaybeTask<IImageProvider>(maskTask.Result); return CreateBlendEffect(bp3); }, bp2, ContinuationOptions); }, bp, ContinuationOptions); }, blendParams, ContinuationOptions).Unwrap().Unwrap()); } } } throw new NotImplementedException(); }