WorkflowInvoker.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / WorkflowInvoker.cs / 1305376 / WorkflowInvoker.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.Activities 
{
    using System; 
    using System.Activities.Hosting; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel;
    using System.Diagnostics.CodeAnalysis;
    using System.Runtime;
    using System.Threading; 

    [Fx.Tag.XamlVisible(false)] 
    public sealed class WorkflowInvoker 
    {
        static AsyncCallback cancelCallback; 
        static AsyncCallback invokeCallback;
        WorkflowInstanceExtensionManager extensions;
        Dictionary pendingInvokes;
        SendOrPostCallback raiseInvokeCompletedCallback; 
        object thisLock;
        Activity workflow; 
 
        public WorkflowInvoker(Activity workflow)
        { 
            if (workflow == null)
            {
                throw FxTrace.Exception.ArgumentNull("workflow");
            } 

            this.workflow = workflow; 
            this.thisLock = new object(); 
        }
 
        public event EventHandler InvokeCompleted;

        public WorkflowInstanceExtensionManager Extensions
        { 
            get
            { 
                if (this.extensions == null) 
                {
                    this.extensions = new WorkflowInstanceExtensionManager(); 
                }

                return this.extensions;
            } 
        }
 
        Dictionary PendingInvokes 
        {
            get 
            {
                if (this.pendingInvokes == null)
                {
                    this.pendingInvokes = new Dictionary(); 
                }
                return this.pendingInvokes; 
            } 
        }
 
        SendOrPostCallback RaiseInvokeCompletedCallback
        {
            get
            { 
                if (this.raiseInvokeCompletedCallback == null)
                { 
                    this.raiseInvokeCompletedCallback = 
                        Fx.ThunkCallback(new SendOrPostCallback(this.RaiseInvokeCompleted));
                } 
                return this.raiseInvokeCompletedCallback;
            }
        }
 
        object ThisLock
        { 
            get 
            {
                return this.thisLock; 
            }
        }

        [Fx.Tag.Throws.Timeout("A timeout occurred when invoking the workflow")] 
        public static IDictionary  Invoke(Activity workflow)
        { 
            return Invoke(workflow, ActivityDefaults.InvokeTimeout); 
        }
 
        [Fx.Tag.InheritThrows(From = "Invoke")]
        public static IDictionary Invoke(Activity workflow, TimeSpan timeout)
        {
            return Invoke(workflow, timeout, null); 
        }
 
        [Fx.Tag.InheritThrows(From = "Invoke")] 
        public static IDictionary Invoke(Activity workflow, IDictionary inputs)
        { 
            return Invoke(workflow, inputs, ActivityDefaults.InvokeTimeout, null);
        }

        [Fx.Tag.InheritThrows(From = "Invoke")] 
        public static IDictionary Invoke(Activity workflow, IDictionary inputs, TimeSpan timeout)
        { 
            return Invoke(workflow, inputs, timeout, null); 
        }
 
        [Fx.Tag.InheritThrows(From = "Invoke")]
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
            Justification = "Generic needed for type inference")]
        public static TResult Invoke(Activity workflow) 
        {
            return Invoke(workflow, null); 
        } 

        [Fx.Tag.InheritThrows(From = "Invoke")] 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
            Justification = "Generic needed for type inference")]
        public static TResult Invoke(Activity workflow, IDictionary inputs)
        { 
            return Invoke(workflow, inputs, ActivityDefaults.InvokeTimeout);
        } 
 
        [Fx.Tag.InheritThrows(From = "Invoke")]
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters, 
            Justification = "Generic needed for type inference")]
        public static TResult Invoke(Activity workflow, IDictionary inputs, TimeSpan timeout)
        {
            IDictionary dummyOutputs; 
            return Invoke(workflow, inputs, out dummyOutputs, timeout);
        } 
 
        [Fx.Tag.InheritThrows(From = "Invoke")]
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters, 
            Justification = "Generic needed for type inference")]
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters,
            Justification = "Arch approved design. Requires the out argument for extra information provided")]
        public static TResult Invoke(Activity workflow, IDictionary inputs, out IDictionary additionalOutputs, TimeSpan timeout) 
        {
            TimeoutHelper.ThrowIfNegativeArgument(timeout); 
            if (inputs != null) 
            {
                additionalOutputs = Invoke(workflow, inputs, timeout, null); 
            }
            else
            {
                additionalOutputs = Invoke(workflow, timeout, null); 
            }
            object untypedResult; 
            if (additionalOutputs.TryGetValue("Result", out untypedResult)) 
            {
                additionalOutputs.Remove("Result"); 
                return (TResult)untypedResult;
            }
            else
            { 
                throw Fx.AssertAndThrow("Activity should always have a output named \"Result\"");
            } 
        } 

        [Fx.Tag.InheritThrows(From = "Invoke")] 
        public IAsyncResult BeginInvoke(AsyncCallback callback, object state)
        {
            return BeginInvoke(this.workflow, ActivityDefaults.InvokeTimeout, this.extensions, callback, state);
        } 

        [Fx.Tag.InheritThrows(From = "Invoke")] 
        public IAsyncResult BeginInvoke(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            TimeoutHelper.ThrowIfNegativeArgument(timeout); 

            return BeginInvoke(this.workflow, timeout, this.extensions, callback, state);
        }
 
        [Fx.Tag.InheritThrows(From = "Invoke")]
        public IAsyncResult BeginInvoke(IDictionary inputs, AsyncCallback callback, object state) 
        { 
            return BeginInvoke(this.workflow, inputs, ActivityDefaults.InvokeTimeout, this.extensions, callback, state);
        } 

        [Fx.Tag.InheritThrows(From = "Invoke")]
        public IAsyncResult BeginInvoke(IDictionary inputs, TimeSpan timeout, AsyncCallback callback, object state)
        { 
            TimeoutHelper.ThrowIfNegativeArgument(timeout);
 
            return BeginInvoke(this.workflow, inputs, timeout, this.extensions, callback, state); 
        }
 
        public void CancelAsync(object userState)
        {
            if (userState == null)
            { 
                throw FxTrace.Exception.ArgumentNull("userState");
            } 
 
            AsyncInvokeContext context = this.RemoveFromPendingInvokes(userState);
            if (context != null) 
            {
                // cancel does not need a timeout since it's bounded by the invoke timeout
                if (cancelCallback == null)
                { 
                    cancelCallback = Fx.ThunkCallback(new AsyncCallback(CancelCallback));
                } 
                // cancel only throws TimeoutException and shouldnt throw at all if timeout is infinite 
                // cancel does not need to raise InvokeCompleted since the InvokeAsync invocation would raise it
                IAsyncResult result = context.WorkflowApplication.BeginCancel(TimeSpan.MaxValue, cancelCallback, context); 
                if (result.CompletedSynchronously)
                {
                    context.WorkflowApplication.EndCancel(result);
                } 
            }
        } 
 
        [Fx.Tag.InheritThrows(From = "Invoke")]
        public IDictionary EndInvoke(IAsyncResult result) 
        {
            return WorkflowApplication.EndInvoke(result);
        }
 
        [Fx.Tag.Throws.Timeout("A timeout occurred when invoking the workflow")]
        public IDictionary Invoke() 
        { 
            return WorkflowInvoker.Invoke(this.workflow, ActivityDefaults.InvokeTimeout, this.extensions);
        } 

        [Fx.Tag.Throws.Timeout("A timeout occurred when invoking the workflow")]
        public IDictionary Invoke(TimeSpan timeout)
        { 
            TimeoutHelper.ThrowIfNegativeArgument(timeout);
 
            return WorkflowInvoker.Invoke(this.workflow, timeout, this.extensions); 
        }
 
        [Fx.Tag.Throws.Timeout("A timeout occurred when invoking the workflow")]
        public IDictionary Invoke(IDictionary inputs)
        {
            return WorkflowInvoker.Invoke(this.workflow, inputs, ActivityDefaults.InvokeTimeout, this.extensions); 
        }
 
        [Fx.Tag.Throws.Timeout("A timeout occurred when invoking the workflow")] 
        public IDictionary Invoke(IDictionary inputs, TimeSpan timeout)
        { 
            TimeoutHelper.ThrowIfNegativeArgument(timeout);

            return WorkflowInvoker.Invoke(this.workflow, inputs, timeout, this.extensions);
        } 

        public void InvokeAsync() 
        { 
            InvokeAsync(ActivityDefaults.InvokeTimeout, null);
        } 

        public void InvokeAsync(TimeSpan timeout)
        {
            InvokeAsync(timeout, null); 
        }
 
        public void InvokeAsync(object userState) 
        {
            InvokeAsync(ActivityDefaults.InvokeTimeout, userState); 
        }

        public void InvokeAsync(TimeSpan timeout, object userState)
        { 
            TimeoutHelper.ThrowIfNegativeArgument(timeout);
 
            InternalInvokeAsync(null, timeout, userState); 
        }
 
        public void InvokeAsync(IDictionary inputs)
        {
            InvokeAsync(inputs, null);
        } 

        public void InvokeAsync(IDictionary inputs, TimeSpan timeout) 
        { 
            InvokeAsync(inputs, timeout, null);
        } 

        public void InvokeAsync(IDictionary inputs, object userState)
        {
            InvokeAsync(inputs, ActivityDefaults.InvokeTimeout, userState); 
        }
 
        public void InvokeAsync(IDictionary inputs, TimeSpan timeout, object userState) 
        {
            if (inputs == null) 
            {
                throw FxTrace.Exception.ArgumentNull("inputs");
            }
            TimeoutHelper.ThrowIfNegativeArgument(timeout); 

            InternalInvokeAsync(inputs, timeout, userState); 
        } 

        [Fx.Tag.Throws.Timeout("A timeout occurred when invoking the workflow")] 
        static IDictionary Invoke(Activity workflow, TimeSpan timeout, WorkflowInstanceExtensionManager extensions)
        {
            if (workflow == null)
            { 
                throw FxTrace.Exception.ArgumentNull("workflow");
            } 
 
            TimeoutHelper.ThrowIfNegativeArgument(timeout);
 
            IDictionary outputs = WorkflowApplication.Invoke(workflow, null, extensions, timeout);

            if (outputs == null)
            { 
                return ActivityUtilities.EmptyParameters;
            } 
            else 
            {
                return outputs; 
            }
        }

        [Fx.Tag.Throws.Timeout("A timeout occurred when invoking the workflow")] 
        static IDictionary Invoke(Activity workflow, IDictionary inputs, TimeSpan timeout, WorkflowInstanceExtensionManager extensions)
        { 
            if (workflow == null) 
            {
                throw FxTrace.Exception.ArgumentNull("workflow"); 
            }

            if (inputs == null)
            { 
                throw FxTrace.Exception.ArgumentNull("inputs");
            } 
 
            TimeoutHelper.ThrowIfNegativeArgument(timeout);
 
            IDictionary outputs = WorkflowApplication.Invoke(workflow, inputs, extensions, timeout);

            if (outputs == null)
            { 
                return ActivityUtilities.EmptyParameters;
            } 
            else 
            {
                return outputs; 
            }
        }

        void AddToPendingInvokes(AsyncInvokeContext context) 
        {
            lock (ThisLock) 
            { 
                if (this.PendingInvokes.ContainsKey(context.UserState))
                { 
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.SameUserStateUsedForMultipleInvokes));
                }
                this.PendingInvokes.Add(context.UserState, context);
            } 
        }
 
        [Fx.Tag.InheritThrows(From = "Invoke")] 
        IAsyncResult BeginInvoke(Activity workflow, IDictionary inputs, TimeSpan timeout, WorkflowInstanceExtensionManager extensions, AsyncCallback callback, object state)
        { 
            if (inputs == null)
            {
                throw FxTrace.Exception.ArgumentNull("inputs");
            } 

            TimeoutHelper.ThrowIfNegativeArgument(timeout); 
 
            return WorkflowApplication.BeginInvoke(workflow, inputs, extensions, timeout, null, null, callback, state);
        } 

        [Fx.Tag.InheritThrows(From = "Invoke")]
        IAsyncResult BeginInvoke(Activity workflow, TimeSpan timeout, WorkflowInstanceExtensionManager extensions, AsyncCallback callback, object state)
        { 
            TimeoutHelper.ThrowIfNegativeArgument(timeout);
 
            return WorkflowApplication.BeginInvoke(workflow, null, extensions, timeout, null, null, callback, state); 
        }
 
        void CancelCallback(IAsyncResult result)
        {
            if (result.CompletedSynchronously)
            { 
                return;
            } 
            AsyncInvokeContext context = (AsyncInvokeContext) result.AsyncState; 
            // cancel only throws TimeoutException and shouldnt throw at all if timeout is infinite
            context.WorkflowApplication.EndCancel(result); 
        }

        void InternalInvokeAsync(IDictionary inputs, TimeSpan timeout, object userState)
        { 
            AsyncInvokeContext context = new AsyncInvokeContext(userState, this);
            if (userState != null) 
            { 
                AddToPendingInvokes(context);
            } 
            Exception error = null;
            bool completedSynchronously = false;
            try
            { 
                if (invokeCallback == null)
                { 
                    invokeCallback = Fx.ThunkCallback(new AsyncCallback(InvokeCallback)); 
                }
                context.Operation.OperationStarted(); 
                IAsyncResult result = WorkflowApplication.BeginInvoke(this.workflow, inputs, this.extensions, timeout, SynchronizationContext.Current, context, invokeCallback, context);
                if (result.CompletedSynchronously)
                {
                    context.Outputs = this.EndInvoke(result); 
                    completedSynchronously = true;
                } 
            } 
            catch (Exception e)
            { 
                if (Fx.IsFatal(e))
                {
                    throw;
                } 
                error = e;
            } 
            if (error != null || completedSynchronously) 
            {
                PostInvokeCompletedAndRemove(context, error); 
            }
        }

        void InvokeCallback(IAsyncResult result) 
        {
            if (result.CompletedSynchronously) 
            { 
                return;
            } 
            AsyncInvokeContext context = (AsyncInvokeContext) result.AsyncState;
            WorkflowInvoker thisPtr = context.Invoker;
            Exception error = null;
            try 
            {
                context.Outputs = thisPtr.EndInvoke(result); 
            } 
            catch (Exception e)
            { 
                if (Fx.IsFatal(e))
                {
                    throw;
                } 
                error = e;
            } 
            thisPtr.PostInvokeCompletedAndRemove(context, error); 
        }
 
        void PostInvokeCompleted(AsyncInvokeContext context, Exception error)
        {
            bool cancelled;
            if (error == null) 
            {
                context.WorkflowApplication.GetCompletionStatus(out error, out cancelled); 
            } 
            else
            { 
                cancelled = false;
            }
            PostInvokeCompleted(context, cancelled, error);
        } 

        void PostInvokeCompleted(AsyncInvokeContext context, bool cancelled, Exception error) 
        { 
            InvokeCompletedEventArgs e = new InvokeCompletedEventArgs(error, cancelled, context);
            if (this.InvokeCompleted == null) 
            {
                context.Operation.OperationCompleted();
            }
            else 
            {
                context.Operation.PostOperationCompleted(this.RaiseInvokeCompletedCallback, e); 
            } 
        }
 
        void PostInvokeCompletedAndRemove(AsyncInvokeContext context, Exception error)
        {
            if (context.UserState != null)
            { 
                RemoveFromPendingInvokes(context.UserState);
            } 
            PostInvokeCompleted(context, error); 
        }
 
        void RaiseInvokeCompleted(object state)
        {
            EventHandler handler = this.InvokeCompleted;
            if (handler != null) 
            {
                handler(this, (InvokeCompletedEventArgs) state); 
            } 
        }
 
        AsyncInvokeContext RemoveFromPendingInvokes(object userState)
        {
            AsyncInvokeContext context;
            lock (ThisLock) 
            {
                if (this.PendingInvokes.TryGetValue(userState, out context)) 
                { 
                    this.PendingInvokes.Remove(userState);
                } 
            }
            return context;
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK