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;
        }
    }
)
\$\endgroup\$

migrated from stackoverflow.com Nov 17 '11 at 16:23

This question came from our site for professional and enthusiast programmers.

  • \$\begingroup\$ Take a look at the tasks parallel Library \$\endgroup\$ – sll Nov 17 '11 at 16:16
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;
            }
        }
    )
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy