Multithreading-Stapelungsklasse

  • Ich muss eine Klasse für Stapelobjekte Order von 3 aufrufenden Komponenten schreiben, die in 3 separaten Threads ausgeführt werden. Die drei aufrufenden Komponenten rufen die Klasse Batcher gleichzeitig (innerhalb einer Sekunde) auf. Um Taktprobleme und Thread-Interleaving zu behandeln, sollte die Methode jedoch maximal 5 Sekunden auf die 3 Aufrufe warten. Wenn es aus irgendeinem Grund nur 2 Aufrufe gibt, sollte der Batcher nach dem 5-Sekunden-Timeout fortfahren und seine Batchverarbeitung fortsetzen. Die Klasse Batcher muss synchron zu den aufrufenden Komponenten erscheinen.

    Ich habe eine Klasse geschrieben, und es scheint zu funktionieren, aber ich bin neu in diesem Bereich und würde es begrüßen jemand könnte meine Klasse überprüfen.

     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;
            }
        }
    )
     
    14 June 2015
    Jamal
1 answer
  • Nicht sicher, was hinter der Anforderung von 5 Sekunden steht, aber von der obersten Ebene (bitte kommentieren, um die als Warnung markierten Elemente zu beantworten):

     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;
                }
            }
        )
     
    18 November 2011
    Arthur P