How to post messages to an STA thread running a message pump?

后端 未结 2 443
鱼传尺愫
鱼传尺愫 2020-11-22 02:05

So, following this, I decided to explicitly instantiate a COM object on a dedicated STA thread. Experiments showed that the COM object needed a message pump, which I created

2条回答
  •  星月不相逢
    2020-11-22 02:31

    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);
    

提交回复
热议问题