first of all a short explanation to my app. I have to present my app on 8 to 16 screens per PC. On each screen is another part of the app. Some are showing videos in an endless repeat, some are showing an endless repeating slideshow and some have even more functionality. Some of the screens are even touchscreens, so it also has to be interactive. But when I call 16 windows on one thread, you can imagine what happens... So I use the following option: Inside the App.xaml.cs I use a foreach and go through all screens. Each screen has a configitem in a xml-file and is called with the screennumber and the kind of what it should show.
But almost at any start it crashes with another errormessage. I only can think of a memoryerror with this kind of multiple GUI threads. Sometimes I get unknown errors, sometimes the XML-Query crashes, sometimes it's the IOStream, and so on...
Has someone an idea what I can do better? Where can I optimize the settings? Or how can I show multiple windows with videos and so on without freezing each other?
For a better understanding what I am doing, I paste my code here.
Here is the XAML:
<Window x:Class="ASA_Videowand.WheelOfFortune"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WheelOfFortune"
Name="WheelWindow"
WindowStyle="None"
Height="1080"
Width="1920"
Loaded="WheelOfFortune_OnLoaded">
<Window.Resources>
<Style x:Key="ImgZIndexStyle" TargetType="{x:Type Image}">
<Setter Property="Panel.ZIndex" Value="2"/>
<Style.Triggers>
<Trigger Property="Image.Opacity" Value="1">
<Setter Property="Panel.ZIndex" Value="3"/>
</Trigger>
</Style.Triggers>
</Style>
<Storyboard x:Key="FaderStoryboardHide1Show2">
<DoubleAnimation Storyboard.TargetName="FirstImage"
Storyboard.TargetProperty="Opacity"
To="0" Duration="0:00:01" />
<DoubleAnimation Storyboard.TargetName="SecondImage"
Storyboard.TargetProperty="Opacity"
To="1" Duration="0:00:01" />
</Storyboard>
<Storyboard x:Key="FaderStoryboardHide2Show1">
<DoubleAnimation Storyboard.TargetName="SecondImage"
Storyboard.TargetProperty="Opacity"
To="0" Duration="0:00:01" />
<DoubleAnimation Storyboard.TargetName="FirstImage"
Storyboard.TargetProperty="Opacity"
To="1" Duration="0:00:01" />
</Storyboard>
</Window.Resources>
<Grid>
<Grid Name="SlideShowGrid" ZIndex="0">
<Image x:Name="FirstImage" Stretch="UniformToFill" Style="{StaticResource ImgZIndexStyle}" Opacity="1" />
<Image x:Name="SecondImage" Stretch="UniformToFill" Style="{StaticResource ImgZIndexStyle}" Opacity="0"/>
</Grid>
<Canvas Name="VideoCanvas" ZIndex="0">
<Button Name="VideoButton" Click="VideoButton_OnClick">
<MediaElement Height="{Binding ElementName=WheelWindow, Path=Height}"
Width="{Binding ElementName=WheelWindow, Path=Width}"
UnloadedBehavior="Manual"
MediaEnded="MarketingVideoMediaElement_OnMediaEnded"
Name="MarketingVideoMediaElement" />
</Button>
</Canvas>
<Grid Name="WheelGrid" ZIndex="1">
<Button Name="SpinWheelButton" Click="SpinWheelButton_OnClick">
<Grid>
<Image Source="pics/gluecksrad_background.jpg" Stretch="UniformToFill" />
<Border>
<Border.Effect>
<DropShadowEffect Direction="330" Opacity="0.7" ShadowDepth="5" Color="Black" BlurRadius="3" RenderingBias="Performance" />
</Border.Effect>
<Image Name="ArrowImage" Source="pics/pfeil.png" Height="300" RenderTransformOrigin="0.5,0.5" Margin="414,330,1390,420">
<Image.RenderTransform>
<RotateTransform />
</Image.RenderTransform>
</Image>
</Border>
</Grid>
</Button>
</Grid>
</Grid>
And the WheelOfFortune.xaml.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Microsoft.Win32;
using Panel = System.Windows.Controls.Panel;
namespace ASA_Videowand
{
public partial class WheelOfFortune
{
private int _listCounter;
private int _imageCounter;
private int _countTimer;
private int _screenNumber;
private List<string> _fileList;
private DoubleAnimation _rotateAnimation;
private readonly int _imageChangeTime;
private readonly string _myPath;
private readonly List<int> _targetAngelList = new List<int>();
private readonly DispatcherTimer _videoTimer = new DispatcherTimer();
private readonly DispatcherTimer _slideShowTimer = new DispatcherTimer();
private static readonly object MyLock = new object();
public WheelOfFortune(int screenNumber, string configName)
{
lock (MyLock)
{
InitializeComponent();
}
BuildList();
CreateVideoTimer();
_screenNumber = screenNumber;
var regKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
var openSubKey = regKey.OpenSubKey(@"SOFTWARE\ASA\Videowand", false);
if (openSubKey != null)
{
_myPath = openSubKey.GetValue("ProgramPath").ToString();
_imageChangeTime = Convert.ToInt32(openSubKey.GetValue("SlideShowTimer"));
}
GetDataFromHdd(configName);
}
private void GetDataFromHdd(string configName)
{
foreach (var fileList in from subDirectory in Directory.GetDirectories(_myPath, "*", SearchOption.AllDirectories)
where subDirectory.Contains(configName)
select Directory.GetFiles(subDirectory, "*", SearchOption.TopDirectoryOnly).ToList())
{
if (fileList[0].ToUpper().Contains(".JPG") || fileList[0].ToUpper().Contains(".GIF") ||
fileList[0].ToUpper().Contains(".JPEG") || fileList[0].ToUpper().Contains(".PNG") ||
fileList[0].ToUpper().Contains(".TIFF") || fileList[0].ToUpper().Contains(".BMP"))
{
_fileList = fileList;
BuildSlideShow();
}
else
ShowMovie(fileList[0]);
}
}
private void ShowMovie(string fileName)
{
CreateVideoStoryboard();
Panel.SetZIndex(VideoCanvas, 2);
MarketingVideoMediaElement.Source = new Uri(fileName);
}
private void BuildSlideShow()
{
Panel.SetZIndex(SlideShowGrid, 2);
WheelGrid.Opacity = 0;
FirstImage.Source = new BitmapImage(new Uri(_fileList[0]));
_slideShowTimer.Interval = new TimeSpan(0, 0, _imageChangeTime);
_slideShowTimer.Tick += Timer_Tick;
_slideShowTimer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
System.Windows.Controls.Image newImage;
Storyboard tempStoryboard;
if (FirstImage.Opacity == 1)
{
tempStoryboard = (Storyboard) FindResource("FaderStoryboardHide1Show2");
newImage = SecondImage;
}
else
{
tempStoryboard = (Storyboard)FindResource("FaderStoryboardHide2Show1");
newImage = FirstImage;
}
if (_imageCounter >= _fileList.Count - 1)
_imageCounter = 0;
else
_imageCounter++;
newImage.Source = new BitmapImage(new Uri(_fileList[_imageCounter]));
tempStoryboard.Begin();
}
private void CreateVideoTimer()
{
_videoTimer.Interval = TimeSpan.FromSeconds(1);
_videoTimer.Tick += VideoTimerOnTick;
}
private void VideoTimerOnTick(object sender, EventArgs eventArgs)
{
_countTimer++;
if (_countTimer <= 8) return;
Panel.SetZIndex(VideoCanvas, 2);
_videoTimer.Stop();
_countTimer = 0;
}
private void BuildList()
{
_targetAngelList.Add(11); // 1 Chip
_targetAngelList.Add(33); // 1 Chip
_targetAngelList.Add(56); // 1 Chip
_targetAngelList.Add(78); // 0 Chips
_targetAngelList.Add(101); // 2 Chips
_targetAngelList.Add(123); // 0 Chips
_targetAngelList.Add(146); // 1 Chip
_targetAngelList.Add(168); // 1 Chip
_targetAngelList.Add(191); // 1 Chip
_targetAngelList.Add(214); // 1 Chip
_targetAngelList.Add(237); // 1 Chip
_targetAngelList.Add(259); // 1 Chip
_targetAngelList.Add(281); // 0 Chips
_targetAngelList.Add(304); // 2 Chips
_targetAngelList.Add(327); // 0 Chips
_targetAngelList.Add(349); // 1 Chip
}
private void SpinWheelButton_OnClick(object sender, RoutedEventArgs e)
{
_countTimer = 0;
var targetAngel = new Random();
_listCounter = targetAngel.Next(0, _targetAngelList.Count - 1);
_rotateAnimation.To = 1800 + _targetAngelList[_listCounter];
((Storyboard)Resources["Storyboard"]).Begin();
}
private void CreateVideoStoryboard()
{
var spinningStoryboard = new Storyboard
{
Duration = new Duration(TimeSpan.FromMilliseconds(2500)),
};
_rotateAnimation = new DoubleAnimation
{
From = 0,
To = 1800 + _targetAngelList[_listCounter],
Duration = spinningStoryboard.Duration,
DecelerationRatio = 0.9
};
Storyboard.SetTarget(_rotateAnimation, ArrowImage);
Storyboard.SetTargetProperty(_rotateAnimation, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));
spinningStoryboard.Children.Add(_rotateAnimation);
Resources.Add("Storyboard", spinningStoryboard);
}
private void VideoButton_OnClick(object sender, RoutedEventArgs e)
{
Panel.SetZIndex(VideoCanvas, 0);
_videoTimer.Start();
}
private void MarketingVideoMediaElement_OnMediaEnded(object sender, RoutedEventArgs e)
{
MarketingVideoMediaElement.Position = new TimeSpan(0, 0, 0, 0, 1);
MarketingVideoMediaElement.Play();
}
private void WheelOfFortune_OnLoaded(object sender, RoutedEventArgs e)
{
ShowOnMonitor();
}
private void ShowOnMonitor()
{
Screen[] screenArray = Screen.AllScreens;
if (_screenNumber >= screenArray.Length)
{
_screenNumber = 0;
}
Left = Convert.ToInt32(screenArray[_screenNumber].Bounds.Left);
Top = Convert.ToInt32(screenArray[_screenNumber].Bounds.Top);
WindowState = WindowState.Maximized;
}
}
}