Is there a way to start the message pump so it does not block?
No. The point of a message queue is that it needs to consume the thread's execution. A message queue is, in implementation, going to look very similar to your:
while(!_stopped)
{
var job = _myBlockingCollection.Take(); // <-- blocks until some job is available
ProcessJob(job);
}
That is a message loop. What you're trying to do is run two different message loops in the same thread. You can't really do that (and have both queues pumping; one queue will, by necessity, pause execution of the other while it is running), it just doesn't make sense.
What you need to do, instead of creating a second message loop on the same thread, is send messages to your existing queue. One way of doing that is through the use of a SynchronizationContext
. One problem however is that there aren't any events that can be hooked into to execute a method in the message pump with that overload of Run
. We'll need to show a Form
just so that we can hook into the Shown
event (at which point we can hide it). We can then grab the SynchronizationContext
and store it somewhere, allowing us to use it to post messages to the message pump:
private static SynchronizationContext context;
public static void SendMessage(Action action)
{
context.Post(s => action(), null);
}
Form blankForm = new Form();
blankForm.Size = new Size(0, 0);
blankForm.Shown += (s, e) =>
{
blankForm.Hide();
context = SynchronizationContext.Current;
};
Application.Run(blankForm);
async/await
to implement and call into an STA apartment. – Verrazano