Lets suppose I have a single class that has two methods OnBarEvent
& Update
.
Update
: subscribes to a continuous stream of data that comes in asynchronously.
OnBarEvent
: will send an event out every n minutes. I am using a timer class to keep track of time and then just have SendEvent attached to the timer class event handler. Essentially, this method will be called whenever N minutes pass
The program will receive asynchronous data via OnEvent which will just summarize the data over a period of time. Once a specified time has passed, then the SendEvent will be called
namespace Common.Aggregator
{
public class BaseTimeAggregator
{
//The last time we emitted a consolidated bar
private DateTime? _lastEmit;
//The minimum timespan between creating new bars.
private readonly TimeSpan? _period;
//The working bar used for aggregating the data
private Bar _workingBar;
//The last working bar
private Bar l_workingBar;
//The Start Time
private DateTime StartTime;
private System.Timers.Timer timer;
public new event EventHandler<Bar> DataConsolidated;
private void OnBarEvent(Object source, System.Timers.ElapsedEventArgs e)
{
if (DateTime.Now > StartTime)
{
if (_workingBar != null)
{
//Console.WriteLine("New Bar: {0}", e.SignalTime);
lock (_workingBar)
{
// Fire Bar
var workingTradeBar = _workingBar as Bar;
if(l_workingBar == null)
{
decimal close_ret = workingTradeBar.Close / workingTradeBar.PreClosePrice;
workingTradeBar.Logret = (decimal)Math.Log((double)close_ret);
}
else
{
// PROBLEM: workingTradeBar can be null here for some reason
decimal value = workingTradeBar.Close / l_workingBar.Close;
workingTradeBar.Logret = (decimal) Math.Log((double)value);
}
l_workingBar = workingTradeBar;
DataConsolidated(this, workingTradeBar);
_workingBar = null;
}
}
}
}
public void Update(Tick data)
{
AggregateBar(data);
}
protected void AggregateBar(Tick data)
{
// Create New Bar
if (_workingBar == null)
{
_workingBar = new Bar(data.LastPrice, data.LastPrice, data.LastPrice, data.LastPrice);
_workingBar.PreClosePrice = data.PreClosePrice;
}
lock (_workingBar)
{
// In the case it got accessed in between
if (_workingBar == null)
{
_workingBar = new Bar(data.LastPrice, data.LastPrice, data.LastPrice, data.LastPrice);
_workingBar.PreClosePrice = data.PreClosePrice;
}
// Update Bar
_workingBar.Update(data.DataType, data.LastPrice, data.BidPrice, data.AskPrice,
data.Volume, data.BidSize, data.AskSize);
}
}
return new DateTime(
dateTime.Year,
dateTime.Month,
dateTime.Day,
hours,
minutes,
seconds,
milliseconds,
dateTime.Kind);
}
}
}
The problem I am running in to is that within the lock, when I access the workingTradeBar
variable (see commented code above where "PROBLEM"), there are situations where its null and throws a system.null error. I can't figure out how it can be null given I made a check right before I entered the lock. Also, the only place I set it null is in the same method since I want to start summarizing the data after N minutes passed.
Thanks
This is different from the other question because its purely a multi-threading problem/race condition.