/// <summary>
 /// constructor
 /// </summary>
 /// <param name="threadStart">
 /// a ThreadStart delegate that represent the block thread<para/>
 /// when stop thread, the unblockFunction will be invoked, then trigger the exit event.
 /// thread unblock and cleanup itself.
 /// </param>
 /// <param name="unblockFunction">
 /// a delegate that is used to unblock the blocked thread.<para/>
 /// for example, when the received thread of TcpClient is blocked at Socket.Receive()<para/>
 /// the ThreadManager will first set the ExitEvent,
 /// then invoke this delegate to close the socket,
 /// and wait for thread to exit<para/>
 /// the thread will unblock from the Socket.Receive() then check the ExitEvent
 /// </param>
 public ThreadManager(ThreadStart threadStart, UnblockFunction unblockFunction)
     : this(threadStart)
 {
     this.unblockFunction = unblockFunction;
 }
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="threadStart">
 /// a ThreadStart delegate that represent the block thread<para/>
 /// when stop thread, the unblockFunction will be invoked, then trigger the exit event.
 /// thread unblock and cleanup itself.
 /// </param>
 /// <param name="unblockFunction">
 /// a delegate that is used to unblock the blocked thread.<para/>
 /// for example, when the received thread of TcpClient is blocked at Socket.Receive()<para/>
 /// the ThreadManager will first set the ExitEvent,
 /// then invoke this delegate to close the socket,
 /// and wait for thread to exit<para/>
 /// the thread will unblock from the Socket.Receive() then check the ExitEvent
 /// </param>
 public ThreadManager(ThreadStart threadStart, UnblockFunction unblockFunction)
     : this(threadStart)
 {
     this.unblockFunction = unblockFunction;
 }