ActiveX Flash component in C# .NET 2.0 Application

2019-06-11 17:25发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

This might be a bit late, but this is my 5 cents:

I think that the .swf (the flash you are playing) is causing the memory leak, i had this issues with flash some time ago, and the solution was to carefully go through the code and to properly stop/clear all timers, dispose all used objects etc. I was debugging with processXP, to see how the flash manages memory, and if you have bad coding practice (not removing EventListeners, not stopping timers, creating new instances and stop using them without proper dispose of them), in time reaches the memory limits and crashes. (crash happens no matter where you have the flash, in browser, stand alone, inside actives etc).

If you are the creator of the .swf, you could pay more attention to that and you wouldn't have to restart your program, but if you are getting it from other sources, you would have to go with closing it periodically, because you don't know how well is coded inside.