// 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 }
// 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); }
// 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)); }
// 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)); }
// 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 }
// 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()); }
// 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()); }
// 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)); }
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(); }