I’m not a big fan of timers, if you want a more event driven approach, try something like this:
public class Foo
{
private AsyncOperation _asyncOperation = null;
private SendOrPostCallback _notifyNewItem = null;
//Make sure you call this on your UI thread.
//Alternatively you can call something like the AttachUI() below later on and catch-up with
//your workers later.
public Foo()
{
this._notifyNewItem = new SendOrPostCallback(this.NewDataInTempList);
this._asyncOperation = AsyncOperationManager.CreateOperation(this);
}
public void AttachUI()
{
if (this._asyncOperation != null)
{
this._asyncOperation.OperationCompleted();
this._asyncOperation = null;
}
this._asyncOperation = AsyncOperationManager.CreateOperation(this);
//This is for catching up with the workers if they’ve been busy already
if (this._asyncOperation != null)
{
this._asyncOperation.Post(this._notifyNewItem, null);
}
}
private int _tempCapacity = 500;
private object _tempListLock = new object();
private List<MyStatus> _tempList = null;
//This gets called on the worker threads..
//Keeps adding to the same list until UI grabs it, then create a new one.
public void Add(MyStatus status)
{
bool notify = false;
lock (_tempListLock)
{
if (this._tempList == null)
{
this._tempList = new List<MyStatus>(this._tempCapacity);
notify = true;
}
this._tempList.Add(status);
}
if (notify)
{
if (this._asyncOperation != null)
{
this._asyncOperation.Post(this._notifyNewItem, null);
}
}
}
//This gets called on your UI thread.
private void NewDataInTempList(object o)
{
List<MyStatus> statusList = null;
lock (this._tempListLock)
{
//Grab the list, and release the lock as soon as possible.
statusList = this._tempList;
this._tempList = null;
}
if (statusList != null)
{
//Deal with it here at your leasure
}
}
}
I’ve used this in a custom Log4Net logger collecting log entries and adding them to a circular array that’s bound to a grid. The performance ended up being pretty good for what it does.