I am working on a .NET Application which is rendering data from a source (say TCP) to excel using the Excel-DNA Library. I have given example of LtpObserver which I have created by implementing IExcelObservable. I am creating the Observer using a Excel Function Call (Refer Code) --> "GetLtp". 'Data' referred here is containing a List of LtpObservers and Ltp value.
THE PROBLEM - When I call the formula in Excel using a symbol say 'X', it creates the Observer (verified via Logging), and the data starts updating. Constructor of observer is called, as well as, callback is received on Subscribe() Method. But, when I call the same formula for 'X in another cell, no new Observer is created, neither a call on subscribe is received. And upon deletion, of formula from just Cell#1, the Dispose is not called. But upon deleting from both Cell#1 and Cell#2 Dispose is called.
So is there just one observer for every unique symbol in the Excel Workbook? In that case does keeping a list of Observers and updating each of them on OnNext() makes sense? And what about the case when 2 or more formulas are used together in a single cell? How does this work Internally
CODE
class LtpObserver : IExcelObservable
{
private List<IExcelObserver> _observerList;
private string _symbol;
private Timer _timer;
public LtpObserver(string symbol)
{
Trace.TraceInformation("Constructor Called. New Ltp Observer Loaded for Symbol : " + symbol);
_symbol = symbol;
_observerList = new List<IExcelObserver>();
_timer = new Timer();
_timer.AutoReset = true;
_timer.Interval = FeedTimerConstant.ltpFrequency;
_timer.Elapsed += _timer_Elapsed;
}
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (Data != null))
{
_timer.Stop();
Data.LtpObserver = _observerList;
timer_tick(Data.Ltp);
}
else
{
timer_tick(0);
}
}
public IDisposable Subscribe(IExcelObserver observer)
{
Trace.TraceInformation("LTP Subscription for : " + observer.ToString() + " Symbol : " + _symbol);
_observerList.Add(observer);
if (Data != null)
{
Data.LtpObserver = _observerList;
timer_tick(Data.Ltp);
}
else
{
timer_tick(0);
_timer.Start();
}
return new ActionDisposable(() => {
Trace.TraceInformation("Un Subscribed for LTP Price :" + _symbol);
_observerList.Remove(observer);
});
}
void timer_tick(object _now)
{
foreach (var obs in _observerList)
obs.OnNext(_now);
}
}
-----------------------------------------------------------------------------------------------------------
[ExcelFunction(Name = "GetLtp", IsVolatile = true)]
public static object GetLtp(string symbol)
{
if (String.IsNullOrEmpty(symbol))
{
return INVALID_SYMBOL;
}
return ExcelAsyncUtil.Observe("GetLtp", symbol, () => new LtpObserver(symbol)
);
}
-------------------------------------------------------------------------------------------------------------
public class Data {
public decimal Ltp { get; set; }
public List<IExcelObserver> LtpObserver { get; set; }
}