views:

1571

answers:

3

We have a C#/.NET 2.0 WinForm with an ActiveX ShockwaveFlashObject control on it. The program loops through a schedule of content and displays it over and over on the control, fullscreen, like this:

axFlash.BringToFront();
axFlash.Movie = scheduleItem.FilePath;
axFlash.Show();
axFlash.Play();

This works great, but after a couple of days running, the form on which the Flash ActiveX control resides will throw an exception like this:

System.Runtime.InteropServices.SEHException: External component has thrown an exception.
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.AxHost.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Looking at the taskmanager, I see that our program has allocated virtually all of the available memory on the machine. (~500MB)

  • Are ActiveX (COM) components unmanaged by Garbage Collection?
  • Is there some known memory leak in Flash9.ocx or Flash10.ocx?
  • Any ideas how I can get an external component (Flash ActiveX in this case) to release resources back without restarting the program? Could periodically re-creating the ShockwaveFlashObject with a "new" fix things?
  • Maybe restarting the program periodically is the only good option?
A: 

If the code in your C# application is simplistic I would recommend just writing it in AIR. This way you aren't dealing with ActiveX and any bugs that Flash's OCX may have.

joshperry
Hmm... some stuff might be difficult to port to AIR. Besides this, changing the platform/language AGAIN (this was originally written in Delphi/Win32) might increase the number of problems, not necessarily reduce it. And who is to say AIR isn't going to have all the same problems that Flash's OCX will - I mean, they are both by Macromedia/Adobe.
Adam Nofsinger
The thing is that the OCX is not Flash itself, it is just an ActiveX wrapper around the flash component. The leak could easily be in that shim and not the actual player code itself. Perhaps there is a small leak that happens in the OCX when a movie is set when one is already currently set. Going directly with AIR would get rid of that shim.
joshperry
It would be easy to do a hardcoded test in AIR that just loops through a few movies over and over. Let it run for a couple days and see if the memory usage is high.
joshperry
+2  A: 

ActiveX components typically are written in unmanaged code, and therefore would not be cleaned up by the CLR garbage collector. You need to ensure you release any references to the ActiveX control. I think this would only create an issue though if you are recreating the ActiveX control a lot.

You can use perfmon to measure memory usage by the CLR and memory usage overall. You can use this to narrow down who is leaking the memory. (the difference would be due to unmanaged code, like the activex control)

If you do isolate it to the ActiveX or flash control, trying stubbing out those objects with a fake object that doesn't consume memory. This should let you verify it is the source of the leak.

Frank Schwieterman
Well, the application itself shouldn't be leaking, it is Garbage Collected. So that leaves the only ActiveX (unmanaged probably) code in the application, the Flash component, as the only culprit. This makes sense too, since the Flash is what was obviously causing the biggest problem when this was a Delphi/Win32 program - you would actually see the Flash stop loading shortly before "the end."
Adam Nofsinger
Its always good to measure to be sure. Maybe the CLR has reserved a whole bunch of memory ahead of time, causing the flash program to run into the out-of-memory condition first. So I don't think that proves where the leak is... better to measure and be sure.
Frank Schwieterman
A: 

Only managed code is garbage collected. ActiveX code use standard COM style collection (AddRef/ReleaseRef). When done using a com reference, set it to null just to be safe, or wrap a using() around it.

Chris Brandsma
The problem there is that the program will never be DONE using it. It is a constantly running Media Player for Digital Signage. Perhaps you mean to imply that calling .Dispose() on it occasionally and then re-creating the instance with "new ShockwaveFlashObject()" would be useful?
Adam Nofsinger