If you are using .NET 4.0 or above, I'd recommend the TPL over threading directly, and I'd recommend using a BlockingCollection<T>
as a way that the UI can "give some work" via the collection for the consumer to do.
The consumer can then be a long-running Task
(again, from the TPL) that consumes from the BlockingCollection<T>
, in this way, you don't need any sleep or manual artifacts like that, the BlockingCollection<T>
lets you block on a wait for a given period of time, then resume once an item is ready to consume.
So you could define a cancellation token source, blocking collection, and task as:
private BlockingCollection<Transaction> _bin = new BlockingCollection<Transaction>();
private CancellationTokenSource _tokenSource = new CancellationTokenSource();
private Task _consumer;
And your consumer method could be defined as:
private void ConsumeTransactions()
{
// loop until consumer marked completed, or cancellation token set
while (!_bin.IsCompleted && !_tokenSource.Token.IsCancelRequested)
{
Transaction item;
// try to take item for 100 ms, or until cancelled
if (_bin.TryTake(out item, 100, _tokenSource.Token)
{
// consume the item
}
}
}
Then you'd fire off the task when your form loads by doing:
// when you have a task running for life of your program, make sure you
// use TaskCreationOptions.LongRunning. This typically sets up its own
// dedicated thread (not pooled) without having to deal with threads directly
_consumer = Task.Factory.StartNew(ConsumeTransactions, _tokenSource.Token,
TaskCreationOptions.LongRunning, TaskScheduler.Default);
And then add items by doing:
_bin.TryAdd(someTransaction);
Where Transaction
is just whatever you define your unit of work to perform...
Then, finally, when your application wants to shut down, it can do:
_bin.CompleteAdding();
Which tells the consumer that no more items will ever be added to the queue, this will make the TryTake()
return false
, and exit the loop since _bin.IsCompleted
will then be true
.
Your long running task can then loop on the blocking get until the cancellation token (also TPL) is set to tell it to shut down...