Synchronous and asynchronous thread control

    In the daily development, a lot of time-consuming work is completed using asynchronous threads, especially in the more common C / S mode, but many times there are resources related to the exclusive lock on the resources of a variety of practices, many time lead to deadlock and lock failure, in which there are a considerable number of MSDN presentation, I will not show oneself. This is mainly done in the attendance of a module, both of manufacture and use MSDN improve both control and application synchronization.

    Reference MSDN topic: " How to: producer and consumer threads to synchronize (C # Programming Guide)"

ExpandedBlockStart.gif MSDN Code
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;

public  class SyncEvents
{
     public SyncEvents()
    {

        _newItemEvent =  new AutoResetEvent( false);
        _exitThreadEvent =  new ManualResetEvent( false);
        _eventArray =  new WaitHandle[ 2];
        _eventArray[ 0] = _newItemEvent;
        _eventArray[ 1] = _exitThreadEvent;
    }

     public EventWaitHandle ExitThreadEvent
    {
         get {  return _exitThreadEvent; }
    }
     public EventWaitHandle NewItemEvent
    {
         get {  return _newItemEvent; }
    }
     public WaitHandle[] EventArray
    {
         get {  return _eventArray; }
    }

     private EventWaitHandle _newItemEvent;
     private EventWaitHandle _exitThreadEvent;
     private WaitHandle[] _eventArray;
}
public  class Producer 
{
     public Producer(Queue< int> q, SyncEvents e)
    {
        _queue = q;
        _syncEvents = e;
    }
     //  Producer.ThreadRun
     public  void ThreadRun()
    {
         int count =  0;
        Random r =  new Random();
         while (!_syncEvents.ExitThreadEvent.WaitOne( 0false))
        {
             lock (((ICollection)_queue).SyncRoot)
            {
                 while (_queue.Count <  20)
                {
                    _queue.Enqueue(r.Next( 0, 100));
                    _syncEvents.NewItemEvent.Set();
                    count++;
                }
            }
        }
        Console.WriteLine( " Producer thread: produced {0} items ", count);
    }
     private Queue< int> _queue;
     private SyncEvents _syncEvents;
}

public  class Consumer
{
     public Consumer(Queue< int> q, SyncEvents e)
    {
        _queue = q;
        _syncEvents = e;
    }
     //  Consumer.ThreadRun
     public  void ThreadRun()
    {
         int count =  0;
         while (WaitHandle.WaitAny(_syncEvents.EventArray) !=  1)
        {
             lock (((ICollection)_queue).SyncRoot)
            {
                 int item = _queue.Dequeue();
            }
            count++;
        } 
        Console.WriteLine( " Consumer Thread: consumed {0} items ", count);
    }
     private Queue< int> _queue;
     private SyncEvents _syncEvents;
}

public  class ThreadSyncSample
{
     private  static  void ShowQueueContents(Queue< int> q)
    {
         lock (((ICollection)q).SyncRoot)
        {
             foreach ( int item  in q)
            {
                Console.Write( " {0}  ", item);
            }
        }
        Console.WriteLine();
    }

     static  void Main()
    {
        Queue< int> queue =  new Queue< int>();
        SyncEvents syncEvents =  new SyncEvents();

        Console.WriteLine( " Configuring worker threads... ");
        Producer producer =  new Producer(queue, syncEvents);
        Consumer consumer =  new Consumer(queue, syncEvents);
        Thread producerThread =  new Thread(producer.ThreadRun);
        Thread consumerThread =  new Thread(consumer.ThreadRun);

        Console.WriteLine( " Launching producer and consumer threads... ");        
        producerThread.Start();
        consumerThread.Start();

         for ( int i= 0; i< 4; i++)
        {
            Thread.Sleep( 2500);
            ShowQueueContents(queue);
        }

        Console.WriteLine( " Signaling threads to terminate... ");
        syncEvents.ExitThreadEvent.Set();

        producerThread.Join();
        consumerThread.Join();
    }

}

 

    Attendance Business Description: Windows Services through a simultaneously monitor multiple attendance. Because the underlying problem Attendance SDK, the various operations can not operate, especially in different operations in different attendance machine can also cause memory access failure, (possibly attendance underlying SDK does not take into account the multiple operations on the part of the same caused by bad memory handling, which is not what we should be the company's problems, the manufacturers can not fix these problems all of a sudden, we only think of ways), action by a thread to handle multiple attendance due to some thought, because the Windows Services no message pump, with a loop at some underlying thread to maintain the status (bottom of the SDK can only be done by a thread created to invoke its methods), the operation of the different attendance to be processed, all are placed in a queue queue in, one by one performed by a loop thread. Although this practice efficiency low point, it can burst for not a lot of business, but it is enough, but also solved the problem of project progress.

    In the example MSDN, the consumer can use the new thread has to work, so

      while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
        {
            lock (((ICollection)_queue).SyncRoot)
            {
                int item = _queue.Dequeue();
            }
            count++;
        } 

Code int  Item = _queue.Dequeue (); there is no problem, as if in attendance, only one thread operation, and Do something after _queue.Dequeue consuming relatively large (can not open a new thread), the practice it is not feasible to complete, and if takes too long, it will have been blocked for manufacturing, undesirable; and the use of AutoResetEvent in SyncEvents, when WaitHandle.WaitAny (_syncEvents.EventArray) will automatically receive the signal recovery, manufacturing by adding an item to the queue, and immediately there is a new signal, no effect of synchronization, therefore, the AutoResetEvent to the ManualResetEvent, when the Do Something completed, and when there is no queue entry, only the manufacturer of the reset signal

 

/// <the Summary> ///  synchronized event control class. MSDN reference to the manufacturer and consumer threads synchronize (C # Programming Guide) /// </ Summary> /// <typeParam name = "T"> T can only AutoResetEvent or the ManualResetEvent </ typeParam> public class  a SyncEvents <T>  WHERE  T: the WaitHandle     { public  a SyncEvents ()         { // _newItemEvent the AutoResetEvent new new = (to false); IF  ( typeof (T) ==  typeof (the AutoResetEvent))                 _newItemEvent =  new new  the AutoResetEvent ( to false ); the else  
    

    
 
    
 
      

        

            
            

               if ( typeof(T) ==  typeof(ManualResetEvent))
                _newItemEvent =  new ManualResetEvent( false);

            _exitThreadEvent =  new ManualResetEvent( false);
            _eventArray =  new WaitHandle[ 2];
            _eventArray[ 0] = _newItemEvent;
            _eventArray[ 1] = _exitThreadEvent;
        }

         ///   <summary>
        
///  退出线程事件。为ManualResetEvent类。
        
///   </summary>
         public EventWaitHandle ExitThreadEvent
        {
             get {  return _exitThreadEvent; }
        }
         ///   <summary>
        
///  新项的消息。为AutoResetEvent类
        
///   </summary>
         public EventWaitHandle NewItemEvent
        {
             get {  return _newItemEvent; }
        }
         ///   <summary>
        
///  事件数组。EventArray[0]为NewItemEvent,NewItemEvent[1]ExitThreadEvent
        
///   </summary>
         public WaitHandle[] EventArray
        {
             get {  return _eventArray; }
        }

         private EventWaitHandle _newItemEvent;
         private EventWaitHandle _exitThreadEvent;
         private WaitHandle[] _eventArray;
    }

 Initialization related entities.

_queue = new Queue<EventsActionEntry>();
 _syncEvents = new SyncEvents<ManualResetEvent>();

m_WorkThread = new Thread(new ThreadStart(CreateEnrollListener));
m_WorkThread.Start();

In the application entities, are not considered manufacturing If you quit, as long as the queue Riga proceeds, and send a signal on it

 

            Console.WriteLine("Receive a message wait for process...");
            lock (((ICollection)_queue).SyncRoot)
            {
                EventsActionEntry entry = new EventsActionEntry { MachineNumber = e.ReceiveData.MachineID, InvokeActionType = ActionType.LogTime};     //生成Action的类型

                _queue.Enqueue(entry);
                _syncEvents.NewItemEvent.Set();
            }

This approach is no more in MSDN change.

Design EventsActionEntry entity that is designed for the user to perform, there is such a phenomenon in many projects, when the first operation is very time-consuming, and the queue of items is increasing, while the middle term has no use, only need to perform the last item, we can lock in the entry of the identity change, but when the user removes the entry, to identify the judge, so that you can perform all Action abandon the middle.

In the method of performing user m_WorkThread = new Thread (new ThreadStart (CreateEnrollListener)); CreateEnrollListener I is used

 

            while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
            {
                EventsActionEntry actionItem = null;
                lock (((ICollection)_queue).SyncRoot)
                {
                    if (_queue.Count > 0)
                        actionItem = _queue.Dequeue();
                }

                // Process events
                ProcessEventAction (actionItem);

                lock (((ICollection)_queue).SyncRoot)
                {
                    if (_queue.Count == 0)
                    {
                        _syncEvents.NewItemEvent.Reset();
                    }
                }
            }

ProcessEventAction (actionItem); a first lock on the outside, so that manufacturers do not block entry to the queue Riga. In this case, the processing NewItemEvent unblocked state, it is possible to perform all the loop has been Action queues, after all the items is completed, the second pair of lock blocking NewItemEvent reset, so the user and the manufacturer waiting added items, as long as the manufacturing by adding a new item, but also a signal to the user, but also to start working again, again and again, to solve the synchronization control of the different threads. In many projects of the unit in order to improve the user experience, the use of these practices (more is to give up in the middle of all operations in many places, as long as the application user clicks on a continuous operation, when in fact only the last stop operation on the line).

    Some statements may be incorrect and unclear, hope that we can get better use of energy improvement, a lot of statements and comments.

Reproduced in: https: //www.cnblogs.com/Yjianyong/archive/2012/08/10/2632310.html

Guess you like

Origin blog.csdn.net/weixin_34370347/article/details/94199617
Recommended