Example #1
0
        // Register a new observable
        // Returns null if it failed (due to RTD array-caller first call)
        static object RegisterObservable(AsyncCallInfo callInfo, IExcelObservable observable)
        {
            // Check it's not registered already
            Debug.Assert(!_asyncCallIds.ContainsKey(callInfo));

            // Set up ObservableState and keep track of things
            // Caller might be null if not from worksheet
            ExcelReference caller = XlCall.Excel(XlCall.xlfCaller) as ExcelReference;
            Guid           id     = Guid.NewGuid();

            Debug.Print("AsyncObservableImpl.RegisterObservable - Id: {0}", id);
            _asyncCallIds[callInfo] = id;
            AsyncObservableState state = new AsyncObservableState(id, callInfo, caller, observable);

            _observableStates[id] = state;

            // Will spin up RTD server and topic if required, causing us to be called again...
            object value;

            if (!state.TryGetValue(out value))
            {
                Debug.Print("AsyncObservableImpl.RegisterObservable (GetValue Error) - Remove Id: {0}", id);
                // Problem case - array-caller with RTD call that failed.
                // Clean up state and return null - we'll be called again later and everything will be better.
                _observableStates.Remove(id);
                _asyncCallIds.Remove(callInfo);
                return(null);
            }
            return(value);
        }
Example #2
0
        // This is the most general RTD registration
        // This should not be called from a ThreadSafe function. Checked in the callers.
        public static object ProcessObservable(string functionName, object parameters, ExcelObservableSource getObservable)
        {
            if (!SynchronizationManager.IsInstalled)
            {
                throw new InvalidOperationException("ExcelAsyncUtil has not been initialized. This is an unexpected error.");
            }
            if (!ExcelDnaUtil.IsMainThread)
            {
                throw new InvalidOperationException("ExcelAsyncUtil.Run / ExcelAsyncUtil.Observe may not be called from a ThreadSafe function.");
            }

            // CONSIDER: Why not same problems with all RTD servers?
            AsyncCallInfo callInfo = new AsyncCallInfo(functionName, parameters);

            // Shortcut if already registered
            Guid id;

            if (_asyncCallIds.TryGetValue(callInfo, out id))
            {
                // Already registered.
                Debug.Print("AsyncObservableImpl GetValueIfRegistered - Found Id: {0}", id);
                AsyncObservableState state = _observableStates[id];
                object value;
                // The TryGetValue call here is a big deal - it eventually calls Excel's RTD function
                // (or not, it the observable is complete).
                // The return value of TryGetValue indicates the special array-call where RTD fails, which we ignore here.
                bool unused = state.TryGetValue(out value);
                return(value);
            }

            // Not registered before - actually register as a new Observable
            IExcelObservable observable = getObservable();

            return(RegisterObservable(callInfo, observable));
        }
Example #3
0
 // caller may be null when not called as a worksheet function.
 public AsyncObservableState(Guid id, AsyncCallInfo callInfo, ExcelReference caller, IExcelObservable observable)
 {
     _id          = id.ToString();
     _callInfo    = callInfo;
     _observable  = observable;
     _callerState = AsyncCallerState.GetCallerState(caller); // caller might be null, _callerState should not be
 }
        // This is the most general RTD registration
        // This should not be called from a ThreadSafe function. Checked in the callers.
        public static object ProcessObservable(string functionName, object parameters, ExcelObservableSource getObservable)
        {
            if (!SynchronizationManager.IsInstalled)
            {
                throw new InvalidOperationException("ExcelAsyncUtil has not been initialized. This is an unexpected error.");
            }
            if (!ExcelDnaUtil.IsMainThread)
            {
                throw new InvalidOperationException("ExcelAsyncUtil.Run / ExcelAsyncUtil.Observe may not be called from a ThreadSafe function.");
            }

            // CONSIDER: Why not same problems with all RTD servers?
            AsyncCallInfo callInfo = new AsyncCallInfo(functionName, parameters);

            // Shortcut if already registered
            object value;

            if (GetValueIfRegistered(callInfo, out value))
            {
                return(value);
            }

            // Actually register as a new Observable
            IExcelObservable observable = getObservable();

            return(RegisterObservable(callInfo, observable));
        }
Example #5
0
 bool Equals(AsyncCallInfo other)
 {
     if (_hashCode != other._hashCode)
     {
         return(false);
     }
     return(Equals(other._functionName, _functionName) &&
            ValueEquals(_parameters, other._parameters));
 }
Example #6
0
        static bool GetValueIfRegistered(AsyncCallInfo callInfo, out object value)
        {
            Guid id;

            if (_asyncCallIds.TryGetValue(callInfo, out id))
            {
                // Already registered.
                AsyncObservableState state = _observableStates[id];
                value = state.GetValue();
                return(true);
            }
            value = null;
            return(false);
        }
Example #7
0
 // caller may be null when not called as a worksheet function.
 public AsyncObservableState(Guid id, AsyncCallInfo callInfo, ExcelReference caller, ExcelObservableOptions options, IExcelObservable observable)
 {
     _callInfo = callInfo;
     if (options == ExcelObservableOptions.None)
     {
         _topics = new string[] { id.ToString() }
     }
     ;
     else
     {
         _topics = new string[] { id.ToString(), ((int)options).ToString() }
     };
     _observable  = observable;
     _callerState = AsyncCallerState.GetCallerState(caller); // caller might be null, _callerState should not be
 }
Example #8
0
        // Register a new observable
        static object RegisterObservable(AsyncCallInfo callInfo, IExcelObservable observable)
        {
            // Check it's not registered already
            Debug.Assert(!_asyncCallIds.ContainsKey(callInfo));

            // Set up a new Id and ObservableState and keep track of things
            Guid id = Guid.NewGuid();

            _asyncCallIds[callInfo] = id;
            AsyncObservableState state = new AsyncObservableState(id, callInfo, observable);

            _observableStates[id] = state;

            // Will spin up RTD server and topic if required, causing us to be called again...
            return(state.GetValue());
        }
Example #9
0
        // Register a new observable
        static object RegisterObservable(AsyncCallInfo callInfo, IExcelObservable observable)
        {
            // Check it's not registered already
            Debug.Assert(!_asyncCallIds.ContainsKey(callInfo));

            // Set up ObservableState and keep track of things
            // Caller might be null if not from worksheet
            ExcelReference caller = XlCall.Excel(XlCall.xlfCaller) as ExcelReference;
            Guid           id     = Guid.NewGuid();

            _asyncCallIds[callInfo] = id;
            AsyncObservableState state = new AsyncObservableState(id, callInfo, caller, observable);

            _observableStates[id] = state;

            // Will spin up RTD server and topic if required, causing us to be called again...
            return(state.GetValue());
        }
Example #10
0
        // This is the most general RTD registration
        // TODO: This should not be called from a ThreadSafe function. Check...?
        public static object ProcessObservable(string functionName, object parameters, ExcelObservableSource getObservable)
        {
            // TODO: Check here that registration has happened.
            // CONSIDER: Why not same problems with all RTD servers?

            AsyncCallInfo callInfo = new AsyncCallInfo(functionName, parameters);

            // Shortcut if already registered
            object value;

            if (GetValueIfRegistered(callInfo, out value))
            {
                return(value);
            }

            // Actually register as a new Observable
            IExcelObservable observable = getObservable();

            return(RegisterObservable(callInfo, observable));
        }
Example #11
0
 public AsyncObservableState(Guid id, AsyncCallInfo callInfo, IExcelObservable observable)
 {
     _id         = id;
     _callInfo   = callInfo;
     _observable = observable;
 }
 public AsyncObservableState(Guid id, AsyncCallInfo callInfo, IExcelObservable observable)
 {
     _id = id;
     _callInfo = callInfo;
     _observable = observable;
 }
        // Register a new observable
        static object RegisterObservable(AsyncCallInfo callInfo, IExcelObservable observable)
        {
            // Check it's not registered already
            Debug.Assert(!_asyncCallIds.ContainsKey(callInfo));

            // Set up a new Id and ObservableState and keep track of things
            Guid id = Guid.NewGuid();
            _asyncCallIds[callInfo] = id;
            AsyncObservableState state = new AsyncObservableState(id, callInfo, observable);
            _observableStates[id] = state;

            // Will spin up RTD server and topic if required, causing us to be called again...
            return state.GetValue();
        }
 static bool GetValueIfRegistered(AsyncCallInfo callInfo, out object value)
 {
     Guid id;
     if (_asyncCallIds.TryGetValue(callInfo, out id))
     {
         // Already registered.
         AsyncObservableState state = _observableStates[id];
         value = state.GetValue();
         return true;
     }
     value = null;
     return false;
 }
        // This is the most general RTD registration
        // TODO: This should not be called from a ThreadSafe function. Check...?
        public static object ProcessObservable(string functionName, object parameters, ExcelObservableSource getObservable)
        {
            // TODO: Check here that registration has happened.
            // CONSIDER: Why not same problems with all RTD servers?

            AsyncCallInfo callInfo = new AsyncCallInfo(functionName, parameters);

            // Shortcut if already registered
            object value;
            if (GetValueIfRegistered(callInfo, out value))
            {
                return value;
            }

            // Actually register as a new Observable
            IExcelObservable observable = getObservable();
            return RegisterObservable(callInfo, observable);
        }
 bool Equals(AsyncCallInfo other)
 {
     if (_hashCode != other._hashCode) return false;
     return Equals(other._functionName, _functionName)
            && ValueEquals(_parameters, other._parameters);
 }