title: How to programmatically exit from a second message loop?
body: <p>I'm trying to create a second message loop to process/filter low level messages asynchronously in C#. It works by creating a hidden form, exposing it's Handle property to be hooked, and run a second message loop in a separate thread. At the moment I'm quite happy with the results but I'm unable to exit from the second loop properly. The only workaround was setting the IsBackground property to true, so the second thread will be simply terminated (without processing all the pending messages) at main application exit.</p>
  
  <p>The question is: how to proper quit that message loop so the second Application.Run() returns? I tried differents approaches creating a separate ApplicationContext and controlling various events (Application.ApplicationExit, Application.ThreadExit, ApplicationContext.ThreadExit) but they all failed with race conditions I'm unable to debug.</p>
  
  <p>Any hint? Thanks</p>
  
  <p>This is the code:</p>
  
  <pre><code>public class MessagePump
  {
      public delegate void HandleHelper(IntPtr handle);
  
      public MessagePump(HandleHelper handleHelper, Filter filter)
      {
          Thread thread = new Thread(delegate()
          {
              ApplicationContext applicationContext = new ApplicationContext();
              Form form = new Form();
              handleHelper(form.Handle);
              Application.AddMessageFilter(new MessageFilter(filter));
              Application.Run(applicationContext);
          });
          thread.SetApartmentState(ApartmentState.STA);
          thread.IsBackground = true; // &lt;-- The workaround
          thread.Start();
      }
  }
  
  public delegate bool Filter(ref Message m);
  
  internal class MessageFilter : IMessageFilter
  {
      private Filter _Filter;
  
      public MessageFilter(Filter filter)
      {
          _Filter = filter;
      }
  
      #region IMessageFilter Members
  
      public bool PreFilterMessage(ref Message m)
      {
          return _Filter(ref m);
      }
  
      #endregion // IMessageFilter Members
  }
  </code></pre>
  
  <p>I use it in the main Form constructor in this way:</p>
  
  <pre><code>_Completion = new ManualResetEvent(false);
  
  MessagePump pump = new MessagePump(
  delegate(IntPtr handle)
  {
      // Sample code, I did this form twain drivers low level wrapping
      _Scanner = new TwainSM(handle);
      _Scanner.LoadDs("EPSON Perfection V30/V300");
  },
  delegate(ref Message m)
  {
      // Asyncrhronous processing of the messages
      // When the correct message is found --&gt;
      _Completion.Set();
  }
  </code></pre>
  
  <p><strong>EDIT</strong>: Full solution in my answer.</p>