currently my program can open the webcam then dynamic capture the human face, however, I have no idea how to stop the camera because it will keep capturing the face even the windows are closed.
private static VideoCapture _cameraCapture;
public VideoSurveilance()
{
InitializeComponent();
Run();
}
void Run()
{
try
{
_cameraCapture = new VideoCapture();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return;
}
_fgDetector = new
Emgu.CV.VideoSurveillance.BackgroundSubtractorMOG2();
_blobDetector = new CvBlobDetector();
_tracker = new CvTracks();
Application.Idle += ProcessFrame;
}
private void btnStopCamera_Click(object sender, EventArgs e)
{
_cameraCapture.Pause();//not working
_cameraCapture.Stop();//not working
_cameraCapture.Dispose();//worked but crashed due to memory issue
this.Close();
faceManipulate fm = new faceManipulate();
fm.Show();
Memory issue already solved. However, Dispose will cause the process frame Null Reference Object.
void ProcessFrame(object sender, EventArgs e)
{
Mat frame = _cameraCapture.QueryFrame();
Mat smoothedFrame = new Mat();
CvInvoke.GaussianBlur(frame, smoothedFrame, new Size(3, 3), 1);
}
You already solved the issue, you should call the Dispose method.
CameraCapture implements DisposableObject, you should not have it as a static variable, instead you should keep it as a variable and dispose when you are done with it.
I saw that you said that it "worked but crashed due to memory issue", if this is still a problem post a question or comment below describing the memory issue.
I noticed this code challenge is old and not many solutions have been posted at this time. However, the provided response will not really solve the issue. I encountered the same problem and found a way around it to avoid the memory NullReferenceError. I will use my own code here for convenience, but the challenges are the same, so it applies. Pick the code section that applies to your instance.
MY OBSERVATIONS
Any Bitmap object has to be disposed (bitmap.Dispose())
properly to free the memory from overload. The natural garbage
collector seems not to pick it up at the end of its function.
The Emgu.CV.Capture _capture; object has to be disposed
(_capture.Dsipose()) as well but has to be done with boolean control to avoid a NullReference error.
public partial class Main : Form
{
bool isStreaming;
bool onCamera;
Capture _capture;
public Main()
{
InitializeComponent();
}
private void btnReset_Click(object sender, EventArgs e)
{
onCamera = false;
isStreaming = false;
if (_capture != null) _capture.Dispose();
if (picStream.Image != null) picStream.Image = null;
if (picCapture.Image != null) picCapture.Image = null;
}
private void btnStream_Click(object sender, EventArgs e)
{
try
{
onCamera = true;
if (_capture != null) _capture.Dispose();
_capture = new Capture();
labelStatus.Text = "Streaming...";
isStreaming = true;
StreamVideo();
Application.Idle += Streaming;
}
catch {}
}
private void Streaming(object sender, EventArgs e)
{
try
{
if(onCamera && isStreaming)
{
if (picStream.Image != null) picStream.Image = null;
var img = _capture.QueryFrame().ToImage<Bgr, byte>();
var bmp = img.Bitmap;
picStream.Image = bmp;
}
}
catch {}
}
private void btnCapture_Click(object sender, EventArgs e)
{
onCamera = true;
CaptureImage();
labelStatus.Text = "Captured!";
if (picCapture.Image != null) picCapture.Image = null;
picCapture.Image = picStream.Image;
}
private void btnLoadCamera_Click(object sender, EventArgs e)
{
try
{
if (!isStreaming)
{
_capture = new Capture();
StreamVideo();
pnlStatus.BackColor = Color.DimGray;
}
else
{
_capture.Dispose();
Application.Idle -= Streaming;
picStream.Visible = true;
picStream.Image = null;
picCapture.Visible = false;
picCapture.Image = null;
isStreaming = false;
pnlStatus.BackColor = Color.DimGray;
}
}
catch {}
}
}
Related
I have a Xamarin.Forms application that supports only UWP. I cannot find a way to print a pdf document. Whatever I have seen on the web, for some reason doesn't work for me. E.g. I tried
https://www.syncfusion.com/kb/8767/how-to-print-pdf-documents-in-xamarin-forms-platform
It lets me print, but the preview in the print dialog never shows up, and the progress indicator just keeps rotating forever.
I also tried http://zawayasoft.com/2018/03/13/uwp-print-pdf-files-silently-without-print-dialog/
This gives me errors that I cannot fix.
So I wonder if somebody can suggest something else that would actually work. Maybe something newer than what I have tried (I use VS 2017). Printing without the printing dialog would be preferable.
Thank you in advance.
I used a very dirty hack to do that!
What I had to do was to try to print the image version of the pdf (I did the conversion in backend) and then used the following DependencyInjection:
Inside my Print class in UWP project:
class Print : IPrint
{
void IPrint.Print(byte[] content)
{
Print_UWP printing = new Print_UWP();
printing.PrintUWpAsync(content);
}
}
and the class responsible for printing in uwp:
public class Print_UWP
{
PrintManager printmgr = PrintManager.GetForCurrentView();
PrintDocument PrintDoc = null;
PrintDocument printDoc;
PrintTask Task = null;
Windows.UI.Xaml.Controls.Image ViewToPrint = new Windows.UI.Xaml.Controls.Image();
public Print_UWP()
{
printmgr.PrintTaskRequested += Printmgr_PrintTaskRequested;
}
public async void PrintUWpAsync(byte[] imageData)
{
int i = 0;
while (i < 5)
{
try
{
BitmapImage biSource = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(imageData.AsBuffer());
stream.Seek(0);
await biSource.SetSourceAsync(stream);
}
ViewToPrint.Source = biSource;
if (PrintDoc != null)
{
printDoc.GetPreviewPage -= PrintDoc_GetPreviewPage;
printDoc.Paginate -= PrintDoc_Paginate;
printDoc.AddPages -= PrintDoc_AddPages;
}
this.printDoc = new PrintDocument();
try
{
printDoc.GetPreviewPage += PrintDoc_GetPreviewPage;
printDoc.Paginate += PrintDoc_Paginate;
printDoc.AddPages += PrintDoc_AddPages;
bool showprint = await PrintManager.ShowPrintUIAsync();
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
// printmgr = null;
// printDoc = null;
// Task = null;
PrintDoc = null;
GC.Collect();
printmgr.PrintTaskRequested -= Printmgr_PrintTaskRequested;
break;
}
catch (Exception e)
{
i++;
}
}
}
private void Printmgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
var deff = args.Request.GetDeferral();
Task = args.Request.CreatePrintTask("Invoice", OnPrintTaskSourceRequested);
deff.Complete();
}
async void OnPrintTaskSourceRequested(PrintTaskSourceRequestedArgs args)
{
var def = args.GetDeferral();
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
args.SetSource(printDoc.DocumentSource);
});
def.Complete();
}
private void PrintDoc_AddPages(object sender, AddPagesEventArgs e)
{
printDoc.AddPage(ViewToPrint);
printDoc.AddPagesComplete();
}
private void PrintDoc_Paginate(object sender, PaginateEventArgs e)
{
PrintTaskOptions opt = Task.Options;
printDoc.SetPreviewPageCount(1, PreviewPageCountType.Final);
}
private void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
{
printDoc.SetPreviewPage(e.PageNumber, ViewToPrint);
}
}
Please note that this is not a perfect solution and sometimes it crashes without actually being able to trace the exception (which is really strange) so I am sure there must be better answers even though it does the job.
With this code i can play video files from my hard disk and show the video in pictureBox1. But i wonder how can i save all the frames of the video to images files on the hard disk ? While playing the video or without playing i need somehow to extract the frames and save them.
This is my used code so far:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
IGraphBuilder m_graphBuilder = null;
IMediaControl m_mediaCtrl = null;
IMediaEventEx m_mediaEvt = null;
IMediaPosition m_mediaPos = null;
IMediaSeeking m_mediaSeeking = null;
public Form1()
{
InitializeComponent();
}
void InitInterfaces()
{
try
{
m_graphBuilder = (IGraphBuilder)new FilterGraph();
m_mediaCtrl = (IMediaControl)m_graphBuilder;
m_mediaEvt = (IMediaEventEx)m_graphBuilder;
m_mediaPos = (IMediaPosition)m_graphBuilder;
m_mediaSeeking = (IMediaSeeking)m_graphBuilder;
}
catch (Exception)
{
MessageBox.Show("Couldn't start directshow graph");
}
}
void CloseInterfaces()
{
if (m_mediaCtrl != null)
{
m_mediaCtrl.StopWhenReady();
}
m_mediaCtrl = null;
m_mediaEvt = null;
m_mediaPos = null;
m_mediaSeeking = null;
if (m_graphBuilder != null)
Marshal.ReleaseComObject(this.m_graphBuilder);
m_graphBuilder = null;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void SetuupVideoRenderer()
{
IBaseFilter vmrFilter = null;
vmrFilter = (IBaseFilter)new VideoMixingRenderer();
m_graphBuilder.AddFilter(vmrFilter, "Video Renderer");
IVMRFilterConfig FilterConfig = (IVMRFilterConfig)vmrFilter;
FilterConfig.SetRenderingMode(VMRMode.Windowless);
IVMRWindowlessControl windowlessCtrl = (IVMRWindowlessControl)vmrFilter;
windowlessCtrl.SetVideoClippingWindow(this.pictureBox1.Handle);
windowlessCtrl.SetVideoPosition(null, DsRect.FromRectangle(pictureBox1.ClientRectangle));
windowlessCtrl.SetAspectRatioMode(VMRAspectRatioMode.LetterBox);
}
private void buttonLoad_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "All Files (*.*)|*.*|mp4 (*.mp4)|*.mp4|mov (*.mov)|*.mov||";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
CloseInterfaces();
InitInterfaces();
SetuupVideoRenderer();
m_graphBuilder.RenderFile(openFileDialog1.FileName, null);
textBoxDur.Text = ( getDuration() * 0.0000001).ToString();
m_mediaCtrl.Run();
timer1.Enabled = true;
}
}
private void GetPosition(out long CurrentPos,out long StopPos)
{
m_mediaSeeking.GetPositions(out CurrentPos, out StopPos);
}
private long getDuration()
{
long duration;
m_mediaSeeking.GetDuration(out duration);
return duration;
}
private void SetPos(double fPos)
{
DsLong startPosition = (DsLong)(10000000 * fPos);
m_mediaSeeking.SetPositions(startPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);
}
private void buttonPause_Click(object sender, EventArgs e)
{
m_mediaCtrl.Pause();
}
private void buttonPlay_Click(object sender, EventArgs e)
{
m_mediaCtrl.Run();
}
private void OnVideoCompleted()
{
MessageBox.Show("Video Playback Completed");
}
private void timer1_Tick(object sender, EventArgs e)
{
long iCurPos, iStopPos;
GetPosition(out iCurPos, out iStopPos);
if (iCurPos >= iStopPos)
{
timer1.Enabled = false;
OnVideoCompleted();
return;
}
textBoxCurPos.Text = (iCurPos * 0.0000001 ).ToString();
}
private void buttonGo_Click(object sender, EventArgs e)
{
SetPos(Convert.ToDouble(textBoxNewPos.Text));
timer1.Enabled = true;
}
}
}
I think this is excatly what you are looking for:
extract frames of a video
Have a look as well at this SO question and the links provided on this webpage.
The easiest way to do it is indeed using an FFMPEG, since its alredy includes some of the most common codecs (if you dont mind extra 30+Mb added to your app). As for wrappers, i used AForge wrapper in the past and really liked it, because of how simple it is to work with. Here is an example from its docs:
// create instance of video reader
VideoFileReader reader = new VideoFileReader();
// open video file
reader.Open( "test.avi");
// read 100 video frames out of it
for ( int i = 0; i < 100; i++)
{
Bitmap videoFrame = reader.ReadVideoFrame();
videoFrame.Save(i + ".bmp")
// dispose the frame when it is no longer required
videoFrame.Dispose( );
}
reader.Close();
I am new to coding in c#. I am building an application to detect the speech and automatically record it. All the information available is based on windows speech recognition engine but my requirement is, the program should detect the speech and record it.
after recording that file is used for processing using hidden markov model(HMM).
namespace Application
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button_1_Click(object sender, EventArgs e)
{
List<NAudio.Wave.WaveInCapabilities> sources = new List<NAudio.Wave.WaveInCapabilities>();
for (int i = 0; i < NAudio.Wave.WaveIn.DeviceCount; i++)
{
sources.Add(NAudio.Wave.WaveIn.GetCapabilities(i));
}
sourceList.Items.Clear();
foreach (var source in sources)
{
ListViewItem item = new ListViewItem(source.ProductName);
item.SubItems.Add(new ListViewItem.ListViewSubItem(item, source.Channels.ToString()));
sourceList.Items.Add(item);
}
}
NAudio.Wave.WaveIn sourceStream = null;
NAudio.Wave.DirectSoundOut waveOut = null;
NAudio.Wave.WaveFileWriter waveWriter = null;
private void button_2_click(object sender, MouseEventArgs e)
{
if (sourceList.SelectedItems.Count == 0) return;
int deviceNumber = sourceList.SelectedItems[0].Index;
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = deviceNumber;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(16000, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels);
sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);
waveWriter = new NAudio.Wave.WaveFileWriter("test.wav", sourceStream.WaveFormat);
sourceStream.StartRecording();
}
private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
{
if (waveWriter == null) return;
waveWriter.WriteData(e.Buffer, 0, e.BytesRecorded);
waveWriter.Flush();
}
private void button_3_click(object sender, EventArgs e)
{
if (waveOut != null)
{
waveOut.Stop();
waveOut.Dispose();
waveOut = null;
}
if (sourceStream != null)
{
sourceStream.StopRecording();
sourceStream.Dispose();
sourceStream = null;
}
if (waveWriter != null)
{
waveWriter.Dispose();
waveWriter = null;
}
speechprocessing.Model_test.speech();
}
private void button4_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
this suits my requirement but it has two button to initiate and terminate the recording process which is not under my requirement..
the program should be running and when the speech is detected it must be recorded and further processed. the words which it should detect is also not too much only a few set of words for which we have made the models using hidden markov model..
so please help me out from this problem.
So my problem is, i created one app for my personal use which fetch the html pages from some sites and then display it in a web browser after some alteration. Every thing is working fine but what perturbed me is the memory that it is taking. After querying for 3-4 terms, memory usage reaches to approximate 300-400 mb.
Some relevant code from the app is
void sentenceBox_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
GC.Collect();
}
HtmlDocument hd;
Word w=new Word();
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
status.Text = "Processing english req..";
if (checkInHis(queryTxt.Text))
{
sentenceBox.AllowNavigation = true;
richTextBox1.Text = w.engDefinition;
sentenceBox.DocumentText = w.engDefinition;
status.Text = "Word found in History.DONE!";
button1.Enabled = true;
return;
}
if (w == null || w.engWordProp != queryTxt.Text)
{
w.engWordProp=queryTxt.Text;
w.loadEngDefn();
w.engDefnLoadedEvent += new Word.engDefnLoaded(w_engDefnLoadedEvent);
return;
}
w.loadEngDefn();
w.engDefnLoadedEvent += new Word.engDefnLoaded(w_engDefnLoadedEvent);
}
void w_engDefnLoadedEvent(Word sender, EventArgs data)
{
sentenceBox.AllowNavigation = true;
sentenceBox.DocumentText = sender.engDefinition;
sender.engDefnLoadedEvent -= w_engDefnLoadedEvent;
button1.Enabled = true;
}
private void addToHistory(Word w)
{
status.Text = "Saving offline...";
if (!checkInHis(w.engWordProp))
{
history.Add(w);
// label1.Text = w.engWordProp + " saved in localdb. Database size: " + history.Count;
w = null;
}
else
{
// label1.Text = w.engWordProp + " Skipped. Database size: " + history.Count;
}
}
private Boolean checkInHis(string p)
{
status.Text = "checking offline storage...";
foreach (Word item in history)
{
if (item.engWordProp == p)
{
status.Text = "Word found in history.";
w = item;
return true;
}
}
status.Text = "Not found in offline database...";
return false;
}
private void sentenceBox_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
((WebBrowser)sender).AllowNavigation = false;
}
private void button2_Click_1(object sender, EventArgs e)
{
button2.Enabled = false;
status.Text = "Requesting hindi definition...";
if (checkInHis(queryTxt.Text))
{
sentenceBox.AllowNavigation = true;
sentenceBox.DocumentText = w.hindiDef;
status.Text = "DONE!";
button2.Enabled = true;
return;
}
if (w == null || w.engWordProp != queryTxt.Text)
{
w.engWordProp=queryTxt.Text;
w.loadHinDefn();
w.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEvent);
return;
}
w.loadHinDefn();
w.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEvent);
}
void w_HindiDefLoadedEvent(Word sender, EventArgs data)
{
sentenceBox.AllowNavigation = true;
sentenceBox.DocumentText = sender.hindiDef;
button2.Enabled = true;
sender.HindiDefLoadedEvent -= w_HindiDefLoadedEvent;
}
private void button3_Click(object sender, EventArgs e)
{
button3.Enabled = false;
saveWord(w);
button3.Enabled = true;
}
private void saveWord(Word w)
{
if (w.hindiDef == "")
{
w.loadHinDefn();
w.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEventforHindiSave);
}
if (w.engDefinition == "")
{
w.loadEngDefn();
w.engDefnLoadedEvent += new Word.engDefnLoaded(w_engDefnLoadedEventforEnglishSave);
}
addToHistory(w);
}
void w_HindiDefLoadedEventforHindiSave(Word sender, EventArgs data)
{
sender.HindiDefLoadedEvent -= w_HindiDefLoadedEvent1;
sender.HindiDefLoadedEvent -= w_HindiDefLoadedEventforHindiSave;
}
void w_engDefnLoadedEventforEnglishSave(Word sender, EventArgs data)
{
sender.engDefnLoadedEvent -= w_engDefnLoadedEventforEnglishSave;
sender.engDefnLoadedEvent -= w_engDefnLoadedEventforEnglishSave;
}
void w_HindiDefLoadedEvent1(Word sender, EventArgs data)
{
saveWord(sender);
sender.HindiDefLoadedEvent -= w_HindiDefLoadedEvent1;
}
void w_engDefnLoadedEvent1(Word sender, EventArgs data)
{
sender.loadHinDefn();
sender.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEvent1);
sender.engDefnLoadedEvent -= w_engDefnLoadedEvent1;
}
void initWord(String query)
{
queryTxt.Text = query;
w.engWordProp=queryTxt.Text;
w.loadEngDefn();
w.loadHinDefn();
w.engDefnLoadedEvent += new Word.engDefnLoaded(w_engDefnLoadedEvent);
w.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEvent);
}
Word class
public Word(string q)
{
wb1 = new WebBrowser();
wb2=new WebBrowser();
engWord = q;
hindiDef = "";
engDefinition = "";
flagE = false;
flagH = false;
engUrl = "http://oxforddictionaries.com/definition/english/" + q + "?q=" + q;
hindiUrl = "http://dict.hinkhoj.com/hindi-dictionary.php?word=" + q;
wb1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted); ;
wb2.DocumentCompleted+=new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
}
public delegate void engDefnLoaded(Word sender, EventArgs data);
public event engDefnLoaded engDefnLoadedEvent;
protected void onEngDefnLoadCompleated(Word sender, EventArgs data)
{
if (engDefnLoadedEvent!=null)
{
engDefnLoadedEvent(this,data);
}
}
public void loadEngDefn()
{
if (this.engDefinition=="")
{
// wb1 = new WebBrowser();
wb1.ScriptErrorsSuppressed = true;
wb1.Url = new Uri(this.engUrl);
}
else
{
if (engDefnLoadedEvent!=null)
{
engDefnLoadedEvent(this, new EventArgs());
}
}
}
public void loadHinDefn() {
if (this.hindiDef=="")
{
// wb2 = new WebBrowser();
wb2.ScriptErrorsSuppressed = true;
wb2.Url = new Uri(this.hindiUrl);
}
else
{
if (HindiDefLoadedEvent!=null)
{
HindiDefLoadedEvent(this, new EventArgs());
}
}
}
[NonSerialized]
HtmlDocument hd;
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (((WebBrowser)sender).ReadyState == WebBrowserReadyState.Complete)
{
hd = ((WebBrowser)sender).Document;
if (e.Url.ToString() == this.hindiUrl)
{
parsePage(hd.GetElementById("maint"), "hindi");
((WebBrowser)sender).DocumentCompleted -= wb_DocumentCompleted;
sender = null;
}
else
{
parsePage(hd.GetElementById("entryPageContent"), "eng");
((WebBrowser)sender).DocumentCompleted -= wb_DocumentCompleted;
sender = null;
}
}
}
private void parsePage(HtmlElement hd, string lan)
{
HtmlElementCollection he;
if (lan == "eng")
{
he = hd.GetElementsByTagName("section");
foreach (HtmlElement item in he)
{
this.engDefinition += item.InnerHtml + "<br>";
}
flagE = true;
engDefnLoadedEvent(this, new EventArgs());
wb1 = null;
wb1.Dispose();
return;
}
else
{
he = hd.GetElementsByTagName("div");
foreach (HtmlElement item in he)
{
if (item.GetAttribute("itemprop") == "itemListElement")
{
this.hindiDef += item.GetElementsByTagName("div")[0].InnerHtml + "<br>";
}
}
flagH = true;
HindiDefLoadedEvent(this,new EventArgs());
wb2 = null;
wb2.Dispose();
return;
}
}
Question: How to remove this memory leak issue ?
sample pic
After query 25 words.
First I'd like to point out that just because your application uses 300 - 400 MB of memory doesn't necessarily mean that you have a memory leak. Only if the memory keeps increasing with each requested page and is never released do you have a leak.
Second, in order to diagnose the problem you need to run a memory profiler. If you are using the Premium or Ultimate edition of Visual Studio, it has a memory profile feature. If not you can use either RedGate Memory Profile (14-day free trial) or similar software.
I would also add that the most common cause for leaks in .NET is the use of events where a short lived object attaches itself as an observer/handler to an event raised by a long lived object.
Well in the constructor of your Word class you have the following code:
wb1 = new WebBrowser();
wb2=new WebBrowser();
The WebBrowser class does is to instantiate some of the web browsing features of your local IE version.My guess is that WebBrowser being a part of the IE it has a high memory consumption.So imagine that you instantiate 2 WebBrowser objects for each word that you have.You could use a pool system for your WebBrowser objects, but i would replace the behavior of those with an WebClient object which is disposable.
P.S. The Garbage Collector system is a fine tuned system using GC.Collect(); it's like using a sledgehammer on your code.
Context: I am playing music through a media element, and using a slider to display the point in the song that it is at. That updating is done in a backgroundworker, for obvious reasons.
private void bgPlay_DoWork(object sender,DoWorkEventArgs e)
{
while (isMediaPlaying)
{
this.Dispatcher.Invoke((Action)(() =>
{
timelineSlider.Value = mediaElement1.Position.TotalMilliseconds;
}));
}
}
private void Library_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
try
{
mediaElement1.Stop();
isMediaPlaying = false;
mediaElement1.Source = new Uri(songData[Library.SelectedIndex].Location);
mediaElement1.Volume = (double)volumeSlider.Value;
mediaElement1.Play();
isMediaPlaying = true;
bgPlay.RunWorkerAsync();
}
catch(Exception ex) {
F.MessageBox.Show(ex.ToString());
}
}
When I play a song, then double click on a different one, the background worker is still looping and throws an exception because it reaches bgPlay.RunWorkerAsync(); before the previous instance has finished. I tried to use the isMediaPlaying bool to tell the backgroundworker when to exit the loop, but the main thread reaches bgPlay.RunWorkerAsync(); before it finishes.
You are suffering of a common mistake when one is barely starting to program with threading, a race condition
I'd advise rewriting the code like this:
private static String threadingLock = "";
private void bgPlay_DoWork(object sender,DoWorkEventArgs e)
{
while (true)
{
lock(threadingLock) {
if(!isMediaPlaying)
break;
}
this.Dispatcher.Invoke((Action)(() =>
{
timelineSlider.Value = mediaElement1.Position.TotalMilliseconds;
}));
}
}
private void Library_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
try
{
lock(threadingLock) {
isMediaPlaying = false;
}
mediaElement1.Stop();
mediaElement1.Source = new Uri(songData[Library.SelectedIndex].Location);
mediaElement1.Volume = (double)volumeSlider.Value;
mediaElement1.Play();
isMediaPlaying = true;
bgPlay.RunWorkerAsync();
}
catch(Exception ex) {
F.MessageBox.Show(ex.ToString());
}
}
As a friendly tip, add a Thread.sleep(200) before invoking the update on the slider. It will reduce cpu usage without affecting the functionality of your application.