C# .NET4.5.2 Win10 SDK6.9 - App Crash at exactly 15 minutes?

Ask software engineering and SDK questions for developers working on Mac OS X, Windows or Linux.
  • Author
  • Message
Offline

George Belicka

  • Posts: 18
  • Joined: Sun Jun 07, 2015 4:07 am

C# .NET4.5.2 Win10 SDK6.9 - App Crash at exactly 15 minutes?

PostSat Dec 03, 2016 8:04 pm

I have the weirdest problem. Here is the setup:

We have been developing some software for use at certain live amateur sporting events. The software tracks teams and scores and winners and things like that. The software can also control an ATEM Television Studio to do things like automatically generate a still image and display it (like a leaderboard) or switch to a live input of the competition or even display a sponsor graphic... It's basically designed to let the event administrator focus on running the event and let the software automate the display of relevant information via the ATEM.

I had some trouble working with the Switcher SDK 6.x from C#, but eventually things settled down enough that I made progress. However, I had some problems with threading, COM and .NET that I never really solved. Specifically, if I create the switcher object on my UI thread, I can't use it from background threads. Any attempt to access the "CreateIterator" method from a background thread would cause QueryInterface errors and fail. Also, some event callbacks/messages like 'bmdSwitcherMediaPoolEventTypeTransferCompleted' happen in a different thread context and don't seem to work properly from a UI thread. (Here is a link to my original exchange with Nicholas Gill regarding this issue: viewtopic.php?f=12&t=36252).

So after some tinkering I came up with a way of making sure I create and access the Switcher object only from an MTA thread. Which not only avoided possible deadlock issues when constantly dispatching to my UI thread, but also fixed my callback/message problems, and generally made life much easier for long running tasks. But my solution came at a price. For some, completely inexplicable reason my application wil crash exactly 15 minutes after I launch it.

I know how it sounds. I must be doing something wrong.

At the time, I didn't have the bandwidth to properly dig into the issue and as a temporary hack I discovered that if I simply disconnected and reconnected the switcher in code every 10 minutes or so, I could avoid the issue. Not my most elegant hack, but it got me through.

Now I am re-visiting the issue, and was able to distill the issue down to a very small code block that replicates the problem. I created a WPF application in Visual Studio 2015 running on Windows 10 and referenced the BMDSwitcher.dll. Here is my code behind:

Code: Select all
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using BMDSwitcherAPI;

namespace SwitcherBomb
{

    public partial class MainWindow : Window
    {

        private IBMDSwitcher m_objSwitcher = null;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnClick(object sender, RoutedEventArgs e)
        {
            var taskCompletionSource = new TaskCompletionSource<object>();
            var thread = new Thread(() =>
            {
                try
                {
                    string szAddress = "192.168.1.240";
                    m_objSwitcher = null;
                    IBMDSwitcherDiscovery objSwitcherDiscovery = new CBMDSwitcherDiscovery();
                    _BMDSwitcherConnectToFailure objFailureReason = 0;
                    try
                    {
                        IBMDSwitcher objLocalSwitcher = null;
                        objSwitcherDiscovery.ConnectTo(szAddress, out objLocalSwitcher, out objFailureReason);
                        if (objLocalSwitcher is IBMDSwitcher)
                        {
                            m_objSwitcher = objLocalSwitcher;
                        }
                    }
                    catch (System.Runtime.InteropServices.COMException)
                    {
                        System.Diagnostics.Debug.WriteLine("Connect failed: {0}", objFailureReason);
                    }
                    taskCompletionSource.SetResult(null);
                }
                catch (Exception ex)
                {
                    taskCompletionSource.SetException(ex);
                }
            });
            thread.SetApartmentState(ApartmentState.MTA);
            thread.Start();
            taskCompletionSource.Task.Wait();
            if (m_objSwitcher is IBMDSwitcher)
            {
                System.Diagnostics.Debug.WriteLine("WooHoo! Switcher connected!");
            }
        }

    }

}


All I have to do is run that code and start my stopwatch and let the app idle for 15 minutes and it will crash. Blammo. Can anyone shed any light on why this might be so? Am I committing some unforgivable sin by creating my switcher inside the MTA thread? If I don't create the switcher inside the MTA thread, how can it be used without dispatching everything to the UI thread? If you are supposed to dispatch everything to the UI thread, then how do I reconcile Nicholas comments last year to use an MTA thread?

I feel like I am missing something important here. :-)

A few final thoughts:

First, I know my real application will exhibit the 15 minute crash on multiple computers. I have not tested the above code on multiple computers. Based on the behavior of my real app, I am going to go out on a limb and say it is not environmental.

Second, I know in the code above I am not holding a reference to the Thread object, so I would assume after the thread completes it must undergo some kind of garbage collection at some point? But holding a reference to the thread did not impact my problem. I also tried invoking DisableComObjectEagerCleanup() before starting the thread but it also did not help.

Third, please realize, my real code is quite a bit more complex. This is simply a boiled down example of how to exhibit the problem. I find that being able to work with the switcher from multiple background threads is preferable to trying to dispatch everything back to the UI.

Fourth, I am also aware that when dealing with multiple threads I have to manage thread access to the physical switcher to avoid multiple threads trying to perform conflicting operations at the same time. I have gatekeeper logic to avoid these kinds of problems.

Any and All suggestions/input/help is appreciated.

Geo...
Offline

Ian Morrish

  • Posts: 580
  • Joined: Sun Jan 18, 2015 9:24 pm
  • Location: New Zealand

Re: C# .NET4.5.2 Win10 SDK6.9 - App Crash at exactly 15 minu

PostSun Dec 04, 2016 4:02 am

I have no such problems with this C# code https://github.com/imorrish/AtemSharp
Have also built some other WPF apps using similar approach which run for days and include switcher events for program, preview and aux.
Regards,
Ian Morrish
Video Integrated Scripting Environment
(Windows PowerShell with ATEM driver + more)
https://ianmorrish.wordpress.com
Offline

George Belicka

  • Posts: 18
  • Joined: Sun Jun 07, 2015 4:07 am

Re: C# .NET4.5.2 Win10 SDK6.9 - App Crash at exactly 15 minu

PostSun Dec 04, 2016 12:36 pm

Ian, thank you for the reply and the pointer to that code. I took a look and unless I am missing something, the entire project you refer to is designed to run on the UI thread. I am also able to work on the UI thread without problems.

As an example: In the AtemSharp example project you reference, in the CallbacksHandlers.cs is a method called GetInputs(). If this code were (hypothetically) part of a long running task, and as such was being executed on a background thread it would not work because the switcher object would fail the QueryInterface induced by the call to CreateIterator(). To demonstrate this, Just wrap the code inside the GetInputs() method in a Task like this:

Code: Select all
private void GetInputs()
{
   Task.Run(() =>
   {
      //Original code body goes here
   });
}


and try running the app. When you click the Connect button to connect to the switcher, it will indeed connect on the UI thread, and when it calls GetInputs (which we have modified to run as a background task without thought to the overall consequence of doing that), it will fail on the CreateIterator(). This is predictable, consistent, and (as shown) easily replicated.

But it drives the developer to wondering what the correct approach is to instancing and using the switcher from a thread other than the UI thread. In my experiments, I have determined that if the switcher is instanced on a background thread and only referenced from background threads and the background threads use MTA for their Apartment State then things stop throwing COM errors and start behaving predictably... but only for about 15 minutes... then splat.

Again, thanks for your interest and response.

Geo...
Offline

matt annis

  • Posts: 5
  • Joined: Wed Oct 18, 2017 6:12 am

Re: C# .NET4.5.2 Win10 SDK6.9 - App Crash at exactly 15 minu

PostMon Oct 23, 2017 10:11 pm

@George

Old Thread I know but did you ever solve this issue? I am seeing a similar inexplicable crash at the 15 min mark using C# to capture from the h264 Pro Recorder. Different hardware yes, but sounds very similar to what you have experienced. Wondering if you ever found a solution here.

Return to Software Developers

Who is online

Users browsing this forum: No registered users and 23 guests