1
\$\begingroup\$

I need to write a class to batch Order objects from 3 calling components running on 3 separate threads. The 3 calling components will call the Batcher class at the same time (within a second of each other), but to handle clock issues and thread interleaving, the method should wait for a maximum of 5 seconds for the 3 calls. If for any reason only 2 calls make it, the batcher should continue after the 5-second timeout and batch what it has. The Batcher class must appear synchronized to the calling components.

I have written a class and it seems to work but I'm new to this and I'd appreciate it if someone could review my class.

public sealed class Batcher
{
 private readonly object _syncLock = new object();
 private readonly Timer _timer;
 private bool _timerSet = false;
 private volatile int _callCount = 0;
 private const int ExecuteImmediatelyCallCount = 3;
 private readonly ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
 private readonly List<Order> _orders = new List<Order>();
 public Batcher()
 {
 _timer = new Timer(Batch, null, Timeout.Infinite, Timeout.Infinite);
 }
 public void TryBatch(IEnumerable<Order> orders)
 {
 lock (_syncLock)
 {
 _orders.AddRange(orders);
 if(!_timerSet)
 {
 _timerSet = true;
 _timer.Change(5000, Timeout.Infinite);
 }
 _callCount ++;
 }
 if(_callCount >= ExecuteImmediatelyCallCount)
 {
 _timer.Change(Timeout.Infinite, Timeout.Infinite);
 Batch(null);
 }
 _manualResetEvent.WaitOne();
 }
 private void Batch(object state)
 {
 lock (_syncLock)
 {
 if(_orders.Count > 0)
 {
 RemoteService.Send(_orders);
 _orders.Clear();
 _manualResetEvent.Reset();
 }
 _callCount = 0;
 }
 }
)
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Nov 17, 2011 at 16:14
\$\endgroup\$
1
  • \$\begingroup\$ Take a look at the tasks parallel Library \$\endgroup\$ Commented Nov 17, 2011 at 16:16

1 Answer 1

1
\$\begingroup\$

Not sure what is behind the requirement of 5 seconds, but from the top level (please comment to answer the items marked as warnings):

public sealed class Batcher
 {
 private readonly object _syncLock = new object();
 private readonly Timer _timer;
 private bool _timerSet = false;
 private volatile int _callCount = 0;
 private const int ExecuteImmediatelyCallCount = 3;
 private readonly ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
 private readonly List<Order> _orders = new List<Order>();
 public Batcher()
 {
 _timer = new Timer(Batch, null, Timeout.Infinite, Timeout.Infinite);
 }
#warning What is the "orders" parameter for
 public void TryBatch(IEnumerable<Order> orders)
 {
#warning don't see a point to lock this operation
 lock (_syncLock)
 {
 _orders.AddRange(orders);
 if(!_timerSet)
 {
 _timerSet = true;
 _timer.Change(5000, Timeout.Infinite);
 }
 _callCount ++;
 }
#warning not thread safe
 if(_callCount >= ExecuteImmediatelyCallCount)
 {
 _timer.Change(Timeout.Infinite, Timeout.Infinite);
 Batch(null);
 }
#warning what is this for?
 _manualResetEvent.WaitOne();
 }
 private void Batch(object state)
 {
 lock (_syncLock)
 {
 if(_orders.Count > 0)
 {
#warning not thread safe
 RemoteService.Send(_orders);
 _orders.Clear();
 _manualResetEvent.Reset();
 }
 _callCount = 0;
 }
 }
 )
answered Nov 17, 2011 at 22:32
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.