Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Ok, so I've encountered a problem not too dissimilar before, but not with WPF, so take the following (very hacky) suggestion with a pinch of salt.</p> <p>The following method basically creates an entirely separate application thread to run directshow commands in, but tells direct show to use the handle of the windows forms control hosted in your WPF application.</p> <p>So, first we need a dummy WinForms form that we can use to invoke calls on, but that is never going to get rendered:</p> <pre><code>/// &lt;summary&gt; /// Just a dummy invisible form. /// &lt;/summary&gt; private class DummyForm : Form { protected override void SetVisibleCore(bool value) { //just override here, make sure that the form will never become visible if (!IsHandleCreated) { CreateHandle(); } value = false; base.SetVisibleCore(value); } } </code></pre> <p>Next step is to create a thread that we can put a message loop on:</p> <pre><code>//this will need to be a class level variable, since all the directshow //calls will get invoked on this form DummyForm dumbForm; Thread separateThread; private void CreateDummyForm() { ManualResetEvent reset = new ManualResetEvent(false); //create our thread separateThread = new Thread((ThreadStart) delegate { //we need a dummy form to invoke on dumbForm = new DummyForm(); //signal the calling method that it can continue reset.Set(); //now kick off the message loop Application.Run(dumbForm); }); //set the apartment state of this new thread to MTA separateThread.SetApartmentState(ApartmentState.MTA); separateThread.IsBackground = true; separateThread.Start(); //we need to wait for the windowing thread to have initialised before we can //say that initialisation is finished reset.WaitOne(); //wait for the form handle to be created, since this won't happen until the form //loads inside Application.Run while (!dumbForm.IsHandleCreated) { Thread.Sleep(0); } } </code></pre> <p>So, once the dummy form (and its thread) have been created, you can invoke calls on the MTA application thread like so:</p> <pre><code>/// &lt;summary&gt; /// Blank delegate, used to represent any Invoke or BeginInvoke target method. /// &lt;/summary&gt; public delegate void InvokeHandler(); //i'm assuming here that DSComponent is a class that all your directshow //code is in, and externalControl is the WinForms control you have embedded in //your application. dumbForm.Invoke(new InvokeHandler(delegate { //maybe something like this? DSComponent.Start(externalControl); })); //and to stop it... dumbForm.Invoke(new InvokeHandler(delegate { DSComponent.Stop(); })); </code></pre> <p>Then, when you're all done with the Directshow stuff, shutdown your separate application thread like so:</p> <pre><code>//to end the separate thread and application loop, //just close your invisible form dumbForm.Close(); </code></pre> <p>Advantage of this approach is that you neatly sandbox directshow into a separate thread. Disadvantage is the context switch of the Invoke calls, plus the overhead of having another application thread. You may have some fun shoehorning this into your current architecture, but it should help.</p> <p>Let me know how you get on, I am intrigued as to how well this works.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload