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();
Related
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 {}
}
}
I created an app for my dad. It's just a simple dictation program. The thing is when he installed it on his computer it stalled and said the general access denied error.
The first time it gave the error I used SaveFileDialog sfd = new SaveFileDialog() then added the usually 'if statement" to make sure the dialog was ok. However the app had an access file denied.
I did the same thing with Environment.GetFolder and it installed on his computer to the location and ran fine. However, when I use the saveFileDialog1 and openFileDialog1 out of the tool box it does not save or open a txt document.
It works on my laptop and not his. Could this be due to an error in the code vs his computer. Also what is the correct way to use the Environement.GetFolder with the SaveFileDialog.
I can also post the full code to the program if needed.
private void lblOpenFile_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
open.Title = "Open File";
open.Filter = "Text Files (*txt) | *.txt";
if (open.ShowDialog() == DialogResult.OK)
{
StreamReader read = new StreamReader(File.OpenRead(open.FileName));
txtTextBox.Text = read.ReadToEnd();
read.Dispose();
}
}
private void lblSaveFile_Click(object sender, EventArgs e)
{
SaveFileDialog save = new SaveFileDialog();
save.Title = "Save File";
save.Filter = "Text Files (*txt) | *.txt";
if (save.ShowDialog() == DialogResult.OK)
{
StreamWriter write = new StreamWriter(File.Create(save.FileName));
write.Write(txtTextBox.Text);
write.Dispose();
}
}
This is the Enviroment i used on my screen recorder. i when i click save it brings up a dialog box i put in the file name press save and it does nothing. It saves the file but not as i specified. So i am trying to merge the above and below codes. The above code does not grant access however the below does
string OutputPath;
OutputPath = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos) + #"\\IvanSoft Desktop Recorder" + saveFileDialog1;
private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
{
string fileName = saveFileDialog1.FileName;
fileName = "Tutorial";
}
the whole code to the program
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Speech.Recognition;
using System.Threading;
namespace AGM_Speech
{
public partial class Form1 : Form
{
public SpeechRecognitionEngine recognizer;
public Grammar grammar;
public Thread RecThread;
public Boolean RecognizerState = true;
public Form1()
{
InitializeComponent();
}
private void lblAbout_Click(object sender, EventArgs e)
{
this.Hide();
About about = new About();
about.Show();
}
private void Form1_Load(object sender, EventArgs e)
{
GrammarBuilder builder = new GrammarBuilder();
builder.AppendDictation();
grammar = new Grammar(builder);
recognizer = new SpeechRecognitionEngine();
recognizer.LoadGrammarAsync(grammar);
recognizer.SetInputToDefaultAudioDevice();
recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized);
RecognizerState = true;
RecThread = new Thread(new ThreadStart(RecThreadFunction));
RecThread.Start();
}
private void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (!RecognizerState)
return;
this.Invoke((MethodInvoker)delegate
{
txtTextBox.Text += (e.Result.Text.ToLower() + " ");
txtTextBox.SelectionStart = txtTextBox.Text.Length - 0;
txtTextBox.SelectionLength = 0;
});
}
public void RecThreadFunction()
{
while (true)
{
try
{
recognizer.RecognizeAsync();
}
catch
{
}
}
}
private void lblStartSpeech_Click(object sender, EventArgs e)
{
RecognizerState = true;
}
private void lblStopSpeech_Click(object sender, EventArgs e)
{
RecognizerState = false;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
RecThread.Abort();
RecThread = null;
grammar = null;
recognizer.UnloadAllGrammars();
recognizer.Dispose();
}
private void lblOpenFile_Click(object sender, EventArgs e)
{
string open = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
StreamReader reader = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
}
private void lblSaveFile_Click(object sender, EventArgs e)
{
SaveFileDialog save = new SaveFileDialog();
save.Title = "Save File";
save.Filter = "Text Files (*txt) | *.txt";
if (save.ShowDialog() == DialogResult.OK)
{
StreamWriter write = new StreamWriter(File.Create(save.FileName));
write.Write(txtTextBox.Text);
write.Dispose();
}
}
private void txtSearch_Click(object sender, EventArgs e)
{
txtSearch.Clear();
lblGo_Click(null, null);
}
private void txtSearch_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)ConsoleKey.Enter)
{
lblGo_Click(null, null);
}
}
private void lblGo_Click(object sender, EventArgs e)
{
int index = 0;
String temp = txtTextBox.Text;
txtTextBox.Text = "";
txtTextBox.Text = temp;
while (index <= txtTextBox.Text.LastIndexOf(txtSearch.Text))
{
txtTextBox.Find(txtSearch.Text, index, txtTextBox.TextLength, RichTextBoxFinds.None);
txtTextBox.SelectionColor = Color.YellowGreen;
index = txtTextBox.Text.IndexOf(txtSearch.Text, index) + 1;
}
}
}
}
It's hard to say where you're failing, because there isn't much in the way of try/catch or logging.
Can you use this instead, and paste the stack trace that shows in the Message Box?
private string fileOutputLocation { get; set; }
private void lblSaveFile_Click(object sender, EventArgs e)
{
bool fileSelected = false;
Try(() =>
{
SaveFileDialog save = new SaveFileDialog();
save.Title = "Save File";
save.Filter = "Text Files (*txt) | *.txt";
save.InitialDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos), "IvanSoft Desktop Recorder");
if (save.ShowDialog() == DialogResult.OK)
{
fileOutputLocation = save.FileName;
fileSelected = true;
}
});
if (fileSelected)
{
bool fileSaved = SaveFile();
MessageBox.Show("File saved successfully: " + fileSaved.ToString());
}
}
private bool SaveFile()
{
TryDeleteFile();
bool fileSaved = false;
Try(()=>
{
File.WriteAllText(fileOutputLocation, txtTextBox.Text);
fileSaved = true;
});
return fileSaved;
}
private void TryDeleteFile()
{
Try(()=>
{
if (File.Exists(fileOutputLocation))
{
File.Delete(fileOutputLocation);
}
});
}
private void Try(Action action)
{
try
{
action();
}
catch (Exception e)
{
MessageBox.Show(string.Format("The following exception was thrown:\r\n{0}\r\n\r\nFile path: {1}", e.ToString(), fileOutputLocation));
}
}
With this, plus the events logged to the Windows Event Viewer (Start>Run>Eventvwr>Security), we should be able to tell you what the problem is.
Lastly, if you're just providing an executable to run, you should check the properties of the file to ensure it's not blocked in Windows.
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.
I was trying to develop a Voice recorder in C#. I have tried many ways, like NAudio, DirectX, Microsoft.Xna.Framework.Audio, etc.
Everything gives the same result. After we stop the recording, the output file mp3/wav get saved.
The mp3/wav file get created at the beginning itself (without and content - 0 bytes)
I am trying to create an application which can save audio live/simultaneously.
private void StartRecording() {
this.WaveSource = new WaveInEvent { WaveFormat = new WaveFormat(44100, 1) };
this.WaveSource.DataAvailable += this.WaveSourceDataAvailable;
this.WaveSource.RecordingStopped += this.WaveSourceRecordingStopped;
this.WaveFile = new WaveFileWriter(#"C:\Sample.wav", this.WaveSource.WaveFormat);
this.WaveSource.StartRecording();
}
private void StopRecording() {
this.WaveSource.StopRecording();
}
void WaveSourceDataAvailable(object sender, WaveInEventArgs e) {
if (this.WaveFile != null) {
this.WaveFile.Write(e.Buffer, 0, e.BytesRecorded);
this.WaveFile.Flush();
}
}
void WaveSourceRecordingStopped(object sender, StoppedEventArgs e) {
if (this.WaveSource != null) {
this.WaveSource.Dispose();
this.WaveSource = null;
}
if (this.WaveFile != null) {
this.WaveFile.Dispose();
this.WaveFile = null;
}
}
I have solved the problem with NAudio library itself.
Few modification to the existing code.
public class Recorder {
WaveIn sourceStream;
WaveFileWriter waveWriter;
readonly String FilePath;
readonly String FileName;
readonly int InputDeviceIndex;
public Recorder(int inputDeviceIndex, String filePath, String fileName) {
InitializeComponent();
this.InputDeviceIndex = inputDeviceIndex;
this.FileName = fileName;
this.FilePath = filePath;
}
public void StartRecording(object sender, EventArgs e) {
sourceStream = new WaveIn {
DeviceNumber = this.InputDeviceIndex,
WaveFormat =
new WaveFormat(44100, WaveIn.GetCapabilities(this.InputDeviceIndex).Channels)
};
sourceStream.DataAvailable += this.SourceStreamDataAvailable;
if (!Directory.Exists(FilePath)) {
Directory.CreateDirectory(FilePath);
}
waveWriter = new WaveFileWriter(FilePath + FileName, sourceStream.WaveFormat);
sourceStream.StartRecording();
}
public void SourceStreamDataAvailable(object sender, WaveInEventArgs e) {
if (waveWriter == null) return;
waveWriter.Write(e.Buffer, 0, e.BytesRecorded);
waveWriter.Flush();
}
private void RecordEnd(object sender, EventArgs e) {
if (sourceStream != null) {
sourceStream.StopRecording();
sourceStream.Dispose();
sourceStream = null;
}
if (this.waveWriter == null) {
return;
}
this.waveWriter.Dispose();
this.waveWriter = null;
recordEndButton.Enabled = false;
Application.Exit();
Environment.Exit(0);
}
}
You can do this with DirectShow.
Take a look at Microsoft's documentation and the project's code samples to learn the best way to configure it according to your needs.
Wanna try to BASS NET?
There is a complete code for you task How to record sound and encode it to mp3? (C#!)
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.