I've written a WPF application that uses many Frame controls to view camera feeds. When deployed, it crashes pretty randomly (anywhere from 2 hours to 16+ hours), and I see these in the event log, consecutively:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.Run() at System.Windows.Application.RunDispatcher(Object ignore) at System.Windows.Application.RunInternal(Window window) at System.Windows.Application.Run(Window window) at System.Windows.Application.Run() at Status_Station_client.MainClass.Main()
Faulting application status station client.exe, version 1.0.0.0, stamp 4ad0faa5, faulting module msvfw32.dll, version 5.1.2600.2180, stamp 41109753, debug? 0, fault address 0x00002642.
Any ideas on how to track this down? The web pages do contain ActiveX controls, so a first guess is there's a problem there.
I haven't been able to trace this in Debug mode. Another thing I have thought of trying is swallowing the exception from the navigation call, but am unsure if this is a wise thing to do:
try
{
if (Frame1 != null)
Frame1.Source = new Uri(uriWithResolution);
}
catch (AccessViolationException ex)
{
// log message
}
EDIT: Here's some more source code, I'm stumped as to where the error is (i.e. where the exception is being thrown)
MatrixView.cs:
public partial class MatrixView : Window
{
System.Timers.Timer timer;
int pageNumber = 0;
IEnumerable<List<CameraInfo>> _cameraList;
GlobalSettings _globalSettings;
Screen _screen;
public MatrixView(List<CameraInfo> cameras, int pageFlipInterval, int camerasPerPage, GlobalSettings globalSettings, Screen screen)
{
InitializeComponent();
_globalSettings = globalSettings;
_screen = screen;
_cameraList = Partition<CameraInfo>(cameras, camerasPerPage);
this.Dispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(Dispatcher_UnhandledException);
displayCameras();
timer = new System.Timers.Timer(pageFlipInterval * 1000); // interval (in seconds) * 1000 ms / s
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
this.KeyUp += new System.Windows.Input.KeyEventHandler(MatrixView_KeyUp);
if (globalSettings.FullScreenOnLoad)
{
this.WindowStyle = WindowStyle.None;
}
}
void MatrixView_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (this.WindowStyle == WindowStyle.None)
{
if (e.Key == Key.F11 || e.Key == Key.Escape)
{
this.WindowStyle = WindowStyle.SingleBorderWindow;
}
}
else
{
if (e.Key == Key.F11)
{
this.WindowStyle = WindowStyle.None;
}
}
this.WindowState = WindowState.Maximized;
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new ThreadStart(delegate()
{
displayCameras();
}));
}
void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
EventLog.WriteEntry("Matrix Monitor", string.Format("Unhandled exception from Matrix Dispatcher\r\nMessage: {0}\r\nSource: {1}\r\nInnerException: {2}\r\nStack Trace: {3}\r\nFull String: {4}", e.Exception.Message, e.Exception.Source, e.Exception.InnerException, e.Exception.StackTrace, e.Exception.ToString()));
e.Handled = true;
}
private void displayCameras()
{
foreach (var child in uniformGrid1.Children)
{
FrameTimer c = child as FrameTimer;
if (c != null)
{
c.Dispose();
c = null;
}
}
GC.Collect();
GC.WaitForPendingFinalizers();
uniformGrid1.Children.Clear();
List<CameraInfo> camerasInPage = _cameraList.ElementAt(pageNumber);
int numCameras = camerasInPage.Count;
int sqrtOfCameras = (int) Math.Sqrt(numCameras);
double height = _screen.Bounds.Height / sqrtOfCameras;
double width = _screen.Bounds.Width / sqrtOfCameras;
foreach (CameraInfo camera in camerasInPage)
{
uniformGrid1.Children.Add(new FrameTimer(camera, _globalSettings, height, width));
}
pageNumber++;
if (pageNumber >= _cameraList.Count<List<CameraInfo>>())
{
pageNumber = 0;
}
}
public static IEnumerable<List<T>> Partition<T>(IList<T> source, int size)
{
int remainder = source.Count % size == 0 ? 0 : 1;
for (int i = 0; i < (source.Count / size) + remainder; i++)
yield return new List<T>(source.Skip(size * i).Take(size));
}
}
FrameTimer.cs:
public partial class FrameTimer : UserControl, IDisposable
{
System.Timers.Timer timer;
string _uri;
string _noImageUrl;
bool? _successState = null;
GlobalSettings _globalSettings;
CameraInfo _camera;
Ping ping;
double _height;
double _width;
public FrameTimer(CameraInfo camera, GlobalSettings globalSettings, double height, double width)
{
InitializeComponent();
_noImageUrl = AppDomain.CurrentDomain.BaseDirectory + "noImage.jpg";
_globalSettings = globalSettings;
_camera = camera;
_height = height;
_width = width;
_uri = string.Format("http://{0}:{1}/LiveView.aspx?camera={2}", globalSettings.ServerIPAddress, globalSettings.ServerPort, camera.camName);
this.Dispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(Dispatcher_UnhandledException);
setUrl();
timer = new System.Timers.Timer(_globalSettings.PingInterval * 1000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
}
void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
EventLog.WriteEntry("Matrix Monitor", string.Format("Unhandled exception from Frame Dispatcher\r\nMessage: {0}\r\nSource: {1}\r\nInnerException: {2}\r\nStack Trace: {3}\r\nFull String: {4}", e.Exception.Message, e.Exception.Source, e.Exception.InnerException, e.Exception.StackTrace, e.Exception.ToString()));
e.Handled = true;
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Send, new ThreadStart(delegate()
{
setUrl();
}));
}
private void setUrl()
{
ping = new Ping();
ping.PingCompleted += new PingCompletedEventHandler(ping_PingCompleted);
videoChecks checks = new videoChecks();
string ipAddressToUse = checks.isIPInternal(_camera.camIP) ? _camera.camIP : _camera.camExtIP;
ping.SendAsync(ipAddressToUse, 1000, null);
}
void ping_PingCompleted(object sender, PingCompletedEventArgs e)
{
try
{
if (e.Reply.Status == IPStatus.Success)
{
if (_successState == null || _successState == false)
{
_successState = true;
string uriWithResolution = string.Format("{0}&res={1}x{2}&header=0", _uri, (int)_width, (int)_height);
if (Frame1 != null)
Frame1.Source = new Uri(uriWithResolution);
}
}
else
{
if (_successState == null || _successState == true)
{
_successState = false;
Image1.Source = new BitmapImage(new Uri(_noImageUrl));
}
}
}
catch (ObjectDisposedException ex)
{
Dispose();
}
finally
{
((IDisposable)sender).Dispose();
}
}
#region IDisposable Members
public void Dispose()
{
if (timer != null)
{
timer.Elapsed -= new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = false;
timer.Dispose();
timer = null;
}
Frame1.Source = null;
if (ping != null)
{
ping.PingCompleted -= new PingCompletedEventHandler(ping_PingCompleted);
((IDisposable)ping).Dispose();
ping = null;
}
}
#endregion
}