System out of memory exception mediaelement wpf - c#

I have screensaver app this app playing video and photo work normally on two hours and i get System out of memory exception how to resolve this problem?
i set the timer for 10 secodns and call SlideShow() method..
private void SlideShow()
{
if (animating == false)
{
animating = true;
if (images.Count <= imgIndex)
imgIndex = 0;
index = images.Count > imgIndex ? imgIndex : 0;
imgIndex++;
fadeOUT.From = 1;
fadeOUT.To = 0;
fadeOUT.Duration = TimeSpan.FromSeconds(CrossFadeTime);
fadeOUT.Completed += new EventHandler(fadeIN_Completed);
fadeIN.From = 0;
fadeIN.To = 1;
fadeIN.Duration = TimeSpan.FromSeconds(CrossFadeTime);
fadeIN.Completed += new EventHandler(fadeIN_Completed);
if (images[index].Contains(".wmv") || images[index].Contains(".mkv") || images[index].Contains(".mp4"))
myMediaElement.Visibility = System.Windows.Visibility.Hidden;
else
{
if (myMediaElement.Visibility == System.Windows.Visibility.Hidden)
myMediaElement.Visibility = System.Windows.Visibility.Visible;
}
myMediaElement.UnloadedBehavior = MediaState.Manual;
myMediaElement.Stop();
myMediaElement.Source = null;
myMediaElement.Close();
myMediaElement.Source = new Uri(images[index], UriKind.RelativeOrAbsolute);
myMediaElement.Stretch = Stretch.Uniform;
myMediaElement.Volume = 0;
myMediaElement1.UnloadedBehavior = MediaState.Manual;
myMediaElement1.Stop();
myMediaElement1.Source = null;
myMediaElement1.Close();
System.Threading.Thread.Sleep(900);
myMediaElement1.Source = new Uri(images[images.Count > index + 1 ? index + 1 : 0], UriKind.RelativeOrAbsolute);
myMediaElement1.Stretch = Stretch.Uniform;
myMediaElement1.MediaOpened += myMediaElement1_MediaOpened;
myMediaElement1.MediaEnded += myMediaElement1_MediaEnded;
myMediaElement.BeginAnimation(Image.OpacityProperty, fadeOUT, HandoffBehavior.SnapshotAndReplace);
myMediaElement1.BeginAnimation(Image.OpacityProperty, fadeIN, HandoffBehavior.SnapshotAndReplace);
}
}

You have to reduce memory consumption of application as much as possible until exception is gone.
You can decrease the memory consumption by just unregister the event when the child window closes.
For example:
myMediaElement1.MediaEnded -= myMediaElement1_MediaEnded;
You can assign null to all MediaElement Properties once Begin Animation is completed and then start BeginAnimation of MediaElement1
myMediaElement.Source=null;
myMediaElement.UnloadedBehavior = null; (if possible)
.
.
This Link further elaborate Memory Leaks

Related

Why getting exception The process cannot access the file image0.gif' because it is being used by another process even if I dispose it first?

private void GenerateAnimatedGifs()
{
UnFreezWrapper unfreezWrapper = new UnFreezWrapper();
checkBoxGetImages = false;
checkBoxGetAllImages.Checked = false;
GetImagesFiles();
for (int i = 0; i < filesSatellite.Length; i++)
{
Image img = Image.FromFile(filesSatellite[i]);
img.Save(filesSatellite[i] + "ConvertedToGif.gif", System.Drawing.Imaging.ImageFormat.Gif);
img.Dispose();
File.Delete(filesSatellite[i]);
}
GetImagesFiles();
unfreezWrapper.MakeGIF(filesRadar.ToList(), #"d:\Downloaded Images\Animates Gifs\radanim.gif", 100, true);
unfreezWrapper.MakeGIF(filesSatellite.ToList(), #"d:\Downloaded Images\Animates Gifs\satanim.gif", 100, true);
}
In the loop I convert each image to gif save it in other name and then dispose the original image and then trying to delete the original image so only the ConvertedToGif images will left.
but I'm getting the exception is being used by another process on the delete line
File.Delete(filesSatellite[i]);
but isn't the file disposed already ?
The problem is that in the constructor I'm loading the images to a pictureBox using timer that is why the images are busy with another process.
If I'm not loading the images at the constructor everything will work fine.
But I want to display the images when running the application and also to be able to convert them to other formats and making other manipulations like creating animated gif of them.
I'm stuck here.
This is the constructor code
public Form1()
{
InitializeComponent();
CheckIfImagesExist();
}
And the code of the CheckIfImagesExist method
private void CheckIfImagesExist()
{
GetImagesFiles();
if (filesRadar != null)
{
if (filesRadar.Length > 1)
{
pictureBox1.Image = new Bitmap(filesRadar[0]);
trackBar1.Enabled = true;
timer1.Enabled = true;
}
if (filesRadar.Length == 1)
{
trackBar1.Enabled = false;
pictureBox1.Image = new Bitmap(filesRadar[0]);
}
}
if (filesSatellite != null)
{
if (filesSatellite.Length > 1)
{
pictureBox2.Image = new Bitmap(filesSatellite[0]);
trackBar1.Enabled = true;
timer2.Enabled = true;
}
if (filesSatellite.Length == 1)
{
trackBar1.Enabled = false;
pictureBox2.Image = new Bitmap(filesSatellite[0]);
}
}
}
The timer tick event
int satImagesCount = 0;
private void timer2_Tick(object sender, EventArgs e)
{
satImagesCount++;
if (satImagesCount == filesSatellite.Length)
{
satImagesCount = 0;
}
pictureBox2.Image = new Bitmap(filesSatellite[satImagesCount]);
if (isInsideSat)
{
pb.Image = new Bitmap(filesSatellite[satImagesCount]);
timer2.Interval = trackBar1.Value * 100;
}
}

MultiMonitor with form and panel

I have 3 monitors connection. I would like to cover up the entire 3 screens with the form and I would like to show the panel just in the center of the primary screen. How should I do this?
Right now I've covered up every screen with this code.
int form_width = 0;
int form_height = 0;
int form_x = 0;
int form_y = 0;
int sub_screen_width = 0;
int sub_screen_height = 0;
bool minus_x = false;
bool minus_y = false;
foreach (Screen screen in Screen.AllScreens)
{
form_width += screen.Bounds.Width;
form_height += screen.Bounds.Height;
if (form_x > screen.Bounds.X)
{
minus_x = true;
form_x = screen.Bounds.X;
}
if (form_y > screen.Bounds.Y)
{
minus_y = true;
form_y = screen.Bounds.Y;
}
if (screen.Bounds.X < 0)
sub_screen_width += screen.Bounds.Width;
if (screen.Bounds.Y < 0)
sub_screen_height += screen.Bounds.Height;
}
this.Width = form_width;
this.Height = form_height;
this.CenterToScreen();
this.Location = new Point(form_x, form_y);
What should I do for the panel??
You could make use of Screen.PrimaryScreen.WorkingArea.
panel1.Location = new Point(Screen.PrimaryScreen.WorkingArea.Left, Screen.PrimaryScreen.WorkingArea.Top);
panel1.Size = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
Btw, To show the form in across Multiple Screen, You dont need to loop through all screens, instead you could make use of VirtualScreen.
this.Size = new System.Drawing.Size(SystemInformation.VirtualScreen.Width,
SystemInformation.VirtualScreen.Height);
this.Location = new Point(SystemInformation.VirtualScreen.Left,
SystemInformation.VirtualScreen.Top);
You could read more on VirtualScreen here

Adding multiple PictureBox to a C# Form

I am trying to add several pictures (using PictureBox) of music notes to a Music Staff Form.
In a certain Mouse Event (MouseUp), a Music Note is created, and a music note should appear on the screen. However, only when the first note is created does the image appear on the screen. For every other note created after the first one, the image does not show up.
In the below method, the Music Note is created:
private void Key_MouseUp(object sender, MouseEventArgs e)
{
foreach (MusKey mk in panel1.Controls)
{
if (sender == mk) //true for the specific key pressed on the Music Keyboard
{
if (e.Button == MouseButtons.Left)
{
timer1.Enabled = false;
sp.Stop();
string bNoteShape = null;
// ticks -> milliseconds
if (count >= 16)
{
bNoteShape = "SemiBreve";
duration = 1024;
}
else if (count >= 8 && count <= 15)
{
bNoteShape = "DotMinim";
duration = 768;
}
else if (count >= 4 && count <= 7)
{
bNoteShape = "Crotchet";
duration = 384;
}
else if (count >= 2 && count <= 3)
{
bNoteShape = "Quaver";
duration = 128;
}
else
{
bNoteShape = "Semi-Quaver";
duration = 90; //63 is too short
}
MusicNote mn = new MusicNote(mk.getMusicNote(), duration, bNoteShape, mk.getNote());
Notes.Add(mn);
mn.picturebox1.Location = new Point(xLoc1, yLoc1);
panel2.Controls.Add(mn.picturebox1); //adding MusicNote component to MusicStaff (panel2) collection
}
}
}
}
When the Note is created, it is sent to the MusicNote constructor:
public MusicNote(int iNotepitch, int iDuration, String iBnoteShape, String iNote)
{
notepitch = iNotepitch;
noteduration = iDuration;
noteshape = iBnoteShape;
note = iNote;
picturebox1.ImageLocation = NoteImage_path + noteshape + ".bmp";
picturebox1.BackColor = Color.Transparent;
picturebox1.Location = new Point(xLoc, yLoc);
xLoc = xLoc + 15;
}
I have tried initializing the location (and incrementing xLoc) both through the constructor, and also in the form itself in method Key_MouseUp, but neither seems to make a difference.
The logic seems to be correct, as the picture of the first music note always loads, but I cannot understand why every other note after the first does not show up on my screen.
Any help will be appreciated, thanks!
Edit: perhaps maybe there is another alternative to PictureBox that I could use to store the music notes?
well it looks like your not initializing a new "picturebox1"
picturebox1 = new PictureBox(); //Add this
picturebox1.ImageLocation = NoteImage_path + noteshape + ".bmp";
edit:
Ok in general we need a few things to add a control to a form.
the new Control (look like you have that) 2
Adding it to the parent control (looks like you have that)
panel2.Controls.Add(mn.picturebox1); //adding MusicNote component to MusicStaff (panel2) collection
redraw the control --
this can happen automatically when you resize the form or you can call refresh(on the panel) after the new control is added to the panel.
panel2.Controls.Add(mn.picturebox1);
panel2.Refresh();

How to make two pictures not visible after a certain time

I'm making a memotest and I need to press two different images and they need to keep visible for 3-5 seconds. I've tried Thread.Sleep(5000) but it doesn't show me the second one. What should I do?
The only way I've founded to see for some seconds the images was by putting a MessageBox but that isn't the idea and I don't know other way to do it.
if (pic != null && pic.Name == fondos[i].Name)
{
if (CantClick == 0)
{
ParejaActual = listRandom[i].pareja;
CantClick = 1;
primerI = i;
picAnterior = pic;
imgAnterior = img;
pic.Visible = false;
}
else if (CantClick == 1)
{
pic.Visible = false;
if (ParejaActual == listRandom[i].pareja)
{
SoundPlayer simpleSound = (new SoundPlayer(Configuracion.RootFolder + "aplau.wav"));
simpleSound.Play();
Ganando++;
label3.Text = Ganando.ToString();
//MessageBox.Show("Si");
//NO SE DESTAPA LA SEGUNDA.
//Thread.Sleep(5000);
CantClick = 0;
img.Visible = false;
imgAnterior.Visible = false;
Application.DoEvents();
}
else
{
(new SoundPlayer(Configuracion.RootFolder + "sad.wav")).Play();
MessageBox.Show("No");
Mal++;
CantClick = 0;
label4.Text = Mal.ToString();
pic.Visible = true;
picAnterior.Visible = true;
}
}
}
Thank you!
Instead of using Thread.Sleep , use System.Timers class. After an interval, just hide one image and show the other. Tell me if you want any other help.

Trying to create a new page when horizontal pos. of i extends past right margin

I am trying add a page when horizontal or the x position is greater than a counter in order to keep a right side margin. When I run the code I end up in an infinate loop of hundreds of pages all displaying the same first page graphics. Thinking it might have to do with my lack of understanding HasMorePages. I could use some help. Thanks.
public static class PrintWave
{
public static void PrintPreWave()
{
PrintDocument pd = new PrintDocument();
if (WaveTools.MySettings == null)
{
pd.DefaultPageSettings.Landscape = true;
}
else
{
pd.DefaultPageSettings = WaveTools.MySettings;
}
pd.OriginAtMargins = true;
pd.PrintPage += new PrintPageEventHandler(OnPrintPage);
PrintDialog dlg = new PrintDialog();
PrintPreviewDialog printPreviewDlg = new PrintPreviewDialog();
printPreviewDlg.Document = pd;
Form p = (Form)printPreviewDlg;
p.WindowState = FormWindowState.Maximized;
printPreviewDlg.ShowDialog();
}
private static void OnPrintPage(object sender, PrintPageEventArgs e)
{
string MyTag = string.Empty;
MyTag = WaveActions.ActiveId;
Wave MyWave = WaveHolder.FindWave(MyTag);
int MyCount = 0;
int xOffset = e.MarginBounds.Location.X;
int yOffset = e.MarginBounds.Location.Y;
if (MyWave != null)
{
Graphics g = e.Graphics;
g.SetClip(e.PageBounds);
Pen MyPen = new Pen(WaveTools.WaveColor, WaveTools.PenWidth);
float dx = (float)e.PageBounds.Width / MyWave.NumSamples;
float dy = (float)e.PageBounds.Height / 255;
if (MyWave.Normal == false)
{
g.ScaleTransform(dx, dy);
}
for (int i = 0; i < MyWave.NumSamples - 1; i++)
{
g.DrawLine(MyPen, i, MyWave.Data[i], i + 1, MyWave.Data[i + 1]);
MyCount = MyCount + 1;
if (MyCount > e.MarginBounds.Width)
{
e.HasMorePages = true;
MyCount = 0;
return;
}
else
{
e.HasMorePages = false;
return;
}
}
}
}
}
}
for (int i = 0; i < MyWave.NumSamples - 1; i++)
That's the core problem statement, you start at 0 every time PrintPage gets called. You need to resume where you left off on the previous page. Make the i variable a field of your class instead of a local variable. Implement the BeginPrint event to set it to zero.
The else clause inside the loop need to be deleted.

Categories