Send or post a message to a Windows Forms message loop

前端 未结 3 430
离开以前
离开以前 2021-02-04 05:29

I have a thread that reads messages from a named pipe. It is a blocking read, which is why it\'s in its own thread. When this thread reads a message, I want it to notify the Win

3条回答
  •  臣服心动
    2021-02-04 06:06

    In WinForms you can achieve this with Control.BeginInvoke. An example:

    public class SomethingReadyNotifier
    {
       private readonly Control synchronizer = new Control();
    
       /// 
       /// Event raised when something is ready. The event is always raised in the
       /// message loop of the thread where this object was created.
       /// 
       public event EventHandler SomethingReady;
    
       protected void OnSomethingReady()
       {
           SomethingReady?.Invoke(this, EventArgs.Empty);
       }
    
       /// 
       /// Causes the SomethingReady event to be raised on the message loop of the
       /// thread which created this object.
       /// 
       /// 
       /// Can safely be called from any thread. Always returns immediately without
       /// waiting for the event to be handled.
       /// 
       public void NotifySomethingReady()
       {
          this.synchronizer.BeginInvoke(new Action(OnSomethingReady));
       }
    }
    

    A cleaner variant of the above which doesn't depend on WinForms would be to use SynchronizationContext. Call SynchronizationContext.Current on your main thread, and then pass that reference to the constructor of the class shown below.

    public class SomethingReadyNotifier
    {
        private readonly SynchronizationContext synchronizationContext;
    
        /// 
        /// Create a new  instance. 
        /// 
        /// 
        /// The synchronization context that will be used to raise
        ///  events.
        /// 
        public SomethingReadyNotifier(SynchronizationContext synchronizationContext)
        {
            this.synchronizationContext = synchronizationContext;
        }
    
        /// 
        /// Event raised when something is ready. The event is always raised
        /// by posting on the synchronization context provided to the constructor.
        /// 
        public event EventHandler SomethingReady;
    
        private void OnSomethingReady()
        {
            SomethingReady?.Invoke(this, EventArgs.Empty);
        }
    
        /// 
        /// Causes the SomethingReady event to be raised.
        /// 
        /// 
        /// Can safely be called from any thread. Always returns immediately without
        /// waiting for the event to be handled.
        /// 
        public void NotifySomethingReady()
        {
            this.synchronizationContext.Post(
                    state => OnSomethingReady(),
                    state: null);
            }
        }
    

提交回复
热议问题