using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TradeIdeas.TIProData;
using TradeIdeas.MiscSupport;
namespace TradeIdeas.TIProGUI
{
///
/// This is a wrapper around StockDataManager to help it work with a GUI.
/// It handles things like automatically unsubscribing to the data when
/// the a window is closed, and moving the callbacks into the correct thread.
///
/// The most obvious approach to threading would be to just wrap each event
/// in a call to BeginInvoke(). However, this could do much more. Perhaps
/// for efficiency we only make one call to BeginInvoke for each message
/// from the server, rather than one for each call to the GUI. Perhaps we
/// consolidate multiple updates when the CPU is taxed.
///
public class StockDataAdapter
{
StockDataManager _stockDataManager =
StockDataManager.Find(GuiEnvironment.FindConnectionMaster("").SendManager);
// Toward the user.
private readonly Control _control;
private readonly Action _callback;
private readonly string[] _formulas;
// Toward the server.
private StockDataManager.Token _token;
public StockDataAdapter(Control control, Action callback, params string[] formulas)
{
_control = control;
_callback = callback;
_formulas = formulas;
control.Disposed += new EventHandler(control_Disposed);
}
void control_Disposed(object sender, EventArgs e)
{
Symbol = null;
}
private string _symbol;
private bool _canceled; // For debugging and assertions, only.
public string Symbol
{
get
{
System.Diagnostics.Debug.Assert(!_canceled);
return _symbol;
}
set
{
System.Diagnostics.Debug.Assert(!_canceled);
if (_symbol == value)
// No change.
return;
_symbol = value;
if (null != _token)
{
_token.Cancel();
_token = null;
}
if (null != _symbol)
{
_token = _stockDataManager.Subscribe(OnResponse, null, _symbol, _formulas);
}
}
}
public void Cancel()
{
Symbol = null;
_control.Disposed -= control_Disposed;
_canceled = true;
}
public RowData RowData { get; set; }
private void OnResponse(StockDataManager.Response response)
{
_control.BeginInvokeIfRequired(delegate
{
if (response.Token != _token)
{ // This can happen sometimes, but it shouldn't happen a lot.
StringBuilder sb = new StringBuilder();
sb.Append(DateTime.Now).Append(" StockDataAdpter.OnResponse(), old token");
if (_canceled)
sb.Append(", this object canceled");
sb.Append(". Token.Symbol=").Append(response.Token.Symbol);
foreach (string formula in response.Token.Formulas)
sb.Append(", Formula=").Append(formula);
sb.Append(". RowData=").Append(response.RowData);
System.Diagnostics.Debug.WriteLine(sb);
}
else
{
RowData = response.RowData;
_callback(this);
}
});
}
}
}