我在wpf项目中使用
Image和MediaElement,我在文件系统中显示图像和视频.我有几个定时器,它们将文件加载到Image / MediaElement控件.一切都工作4-5小时,但MediaElement视频文件冻结,MediaEnded事件不会发生.我重新启动应用程序,它运行没有任何问题,但几个小时后,这个问题再次出现.
我的WPF XAML代码:
<Grid Name="MainGrid"> <Image HorizontalAlignment="Center" VerticalAlignment="Center" Name="MainImage" Stretch="Fill" /> <MediaElement MediaEnded="MediaEnded" MediaOpened="MediaOpened" LoadedBehavior="Manual" HorizontalAlignment="Center" Name="VideoControl" VerticalAlignment="Center" Stretch="Fill" UnloadedBehavior="Manual"/> </Grid>
C#代码:
public partial class ImageView { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); private static String _advCheckGuid; private List<String> _FolderNames; private int _FolderIndex = 0; private MainWindow _MainWindow; private List<String> _PathList; private List<String> _CheckPathList; private int _Index; private BitmapImage _BitmapImage; private volatile bool _Running = true; private Backend _Backend; private ApplicationDeployment _UpdateCheck; // Threads private Timer _ImageTimer; private Timer _UpdateTimer; private Timer _FolderClearTimer; private Timer _CheckApplicationUpdateTimer; private Thread _TerminationThread; public ImageView() { InitializeComponent(); _PathList = new List<string>(); _CheckPathList = new List<string>(); _Index = 0; } private void ViewPageLoaded(Object sender,EventArgs e) { _FolderNames = new List<string> { Constants.AdsFolderFirst,Constants.AdsFolderSecond }; _Backend = new Backend(); _MainWindow = (MainWindow)Window.GetWindow(this); _ImageTimer = new Timer(Constants.DefaultImageTimer); _ImageTimer.Elapsed += ChangeImageSource; _ImageTimer.Start(); } private void ChangeImageSource(object sender,System.Timers.ElapsedEventArgs e) { Application.Current.Dispatcher.Invoke( DispatcherPriority.Normal,new Action( delegate() { try { if (MainImage != null && MainImage.Source != null) { MainImage.Source = null; } if (VideoControl != null && VideoControl.Source != null) { VideoControl.Stop(); VideoControl.Source = null; } if (_Index >= _PathList.Count) { _Index = 0; } if (_PathList.ElementAt(_Index) != null) { Log.Info(String.Format("Start [ChangeImageSource]. Element: {0},Index: {1}",_PathList.ElementAt(_Index),_Index)); try { _ImageTimer.Stop(); String[] checkExt = _PathList.ElementAt(_Index).Split('.'); String ext = checkExt[checkExt.Length - 1]; if (ext.Equals("jpg",StringComparison.CurrentCultureIgnoreCase) || ext.Equals("jpeg",StringComparison.CurrentCultureIgnoreCase) || ext.Equals("png",StringComparison.CurrentCultureIgnoreCase)) { _ImageTimer.Interval = Constants.NormalImageTimer; ShowImage(_PathList.ElementAt(_Index)); } else if (ext.Equals("mp4",StringComparison.CurrentCultureIgnoreCase) || ext.Equals("3gp",StringComparison.CurrentCultureIgnoreCase)) { _ImageTimer.Interval = Constants.VideoDefaultTimer; PlayQueue(_PathList.ElementAt(_Index)); } _ImageTimer.Start(); _Index++; } catch (Exception exception) { Log.ErrorException(exception.Message,exception); } } } catch (Exception exception) { Log.ErrorException(exception.Message,exception); } })); } private void ShowImage(String fileName) { try { if (!String.IsNullOrEmpty(fileName)) { _BitmapImage = LoadImage(fileName); MainImage.Source = _BitmapImage; } } catch (Exception e) { Log.ErrorException(e.Message,e); } } private void PlayQueue(String fileName) { try { if (!String.IsNullOrEmpty(fileName)) { VideoControl.LoadedBehavior = MediaState.Play; VideoControl.Source = new Uri(fileName,UriKind.Absolute); } } catch (Exception e) { Log.ErrorException(e.Message,e); } } private void MediaEnded(object sender,EventArgs e) { try { if (MainImage != null && MainImage.Source != null) { MainImage.Source = null; } if (VideoControl != null && VideoControl.Source != null) { VideoControl.Stop(); VideoControl.Source = null; } if (_Index >= _PathList.Count) { _Index = 0; } if (_PathList.ElementAt(_Index) != null) { Log.Info(String.Format("Start [MediaEnded oper]. Element: {0},_Index)); try { _ImageTimer.Stop(); String[] checkExt = _PathList.ElementAt(_Index).Split('.'); String ext = checkExt[checkExt.Length - 1]; if (ext.Equals("jpg",StringComparison.CurrentCultureIgnoreCase) || ext.Equals("jpeg",StringComparison.CurrentCultureIgnoreCase) || ext.Equals("png",StringComparison.CurrentCultureIgnoreCase)) { _ImageTimer.Interval = Constants.NormalImageTimer; ShowImage(_PathList.ElementAt(_Index)); } else if (ext.Equals("mp4",StringComparison.CurrentCultureIgnoreCase) || ext.Equals("3gp",StringComparison.CurrentCultureIgnoreCase)) { _ImageTimer.Interval = Constants.VideoDefaultTimer; PlayQueue(_PathList.ElementAt(_Index)); } _ImageTimer.Start(); _Index++; } catch (Exception exception) { Log.ErrorException(exception.Message,exception); } } } catch (Exception exception) { Log.ErrorException(exception.Message,exception); } } private void MediaOpened(object sender,EventArgs e) { } private BitmapImage LoadImage(string myImageFile) { BitmapImage myRetVal = null; if (!String.IsNullOrEmpty(myImageFile)) { var image = new BitmapImage(); try { using (FileStream stream = File.OpenRead(myImageFile)) { image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.StreamSource = stream; image.EndInit(); } } catch (Exception exception) { Log.ErrorException(exception.Message,exception); } myRetVal = image; } return myRetVal; }
解决方法
我用Google搜索,发现这是与软件渲染相关的WPF图形问题.通过将这段代码添加到ViewPageLoaded方法中来解决该问题.
try { var hwndSource = PresentationSource.FromVisual(this) as HwndSource; var hwndTarget = hwndSource.CompositionTarget; hwndTarget.RenderMode = RenderMode.SoftwareOnly; } catch (Exception ex) { Log.ErrorException(ex.Message,ex); }
它帮助我解决了这个问题.希望它也会对你有所帮助.