WebClient Retry - c#

Is it possible to retry a webclient request? On the odd occasion my application will throw an error when attempting to connect to an xml web service but if I retry, it works OK. I'd like it to retry 2 times before throwing an error unless someone has a better solution :)
private void ApplicationBarLogin_Click(object sender, EventArgs e)
{
settings.UsernameSetting = Username.Text;
if (RememberPassword.IsChecked == true)
{
settings.PasswordSetting = Password.Password;
settings.RememberPasswordSetting = true;
}
else
{
settings.RememberPasswordSetting = false;
}
WebClient internode = new WebClient();
internode.Credentials = new NetworkCredential(settings.UsernameSetting, settings.PasswordSetting);
internode.DownloadStringCompleted += new DownloadStringCompletedEventHandler(internode_DownloadStringCompleted);
internode.DownloadStringAsync(new Uri("https://customer-webtools-api.internode.on.net/api/v1.5/"));
}
public void internode_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else
{
MessageBox.Show("Authentication successfull.");
}
}

If you get a failure, you could re-issue the request. By keeping count of the number of times you re-issue the request you can determine when to show the user an error. Here is a quick modification to your code to demonstrate what I mean.
private void ApplicationBarLogin_Click(object sender, EventArgs e)
{
settings.UsernameSetting = Username.Text;
if (RememberPassword.IsChecked == true)
{
settings.PasswordSetting = Password.Password;
settings.RememberPasswordSetting = true;
}
else
{
settings.RememberPasswordSetting = false;
}
WebClient internode = new WebClient();
internode.Credentials = new NetworkCredential(settings.UsernameSetting, settings.PasswordSetting);
internode.DownloadStringCompleted += new DownloadStringCompletedEventHandler(internode_DownloadStringCompleted);
internode.DownloadStringAsync(new Uri("https://customer-webtools-api.internode.on.net/api/v1.5/"));
}
private int _retryCount = 0;
public void internode_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
{
_retryCount++;
if (_retryCount < 3)
{
WebClient internode = (WebClient)sender;
internode.DownloadStringAsync(new Uri("https://customer-webtools-api.internode.on.net/api/v1.5/"));
}
else
{
_retryCount = 0;
MessageBox.Show(e.Error.Message);
}
}
else
{
_retryCount = 0;
MessageBox.Show("Authentication successfull.");
}
}

WebClient doesn't have any built in retry functionality.
You should look to build the retry logic yourself before, probably, informing the user of the problem.

Related

How to receive data from a server?

I'm coding a chat application with C# Windows Froms. My problem is that, my server can send messages to each connected client but only a client that sent a message can receive a response. I tried to create a function like ReceiveLoop() with an infinite loop inside or add a timer and call Receive() function for each tick but both were unsuccessful due to the app's crash.
How to get the data in real time? I attach my client's app code.
public partial class Form1 : Form
{
private string name;
private Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private void Namebt_Click(object sender, EventArgs e)
{
if (!Test(Nametb.Text)) Nametb.Text = "Nie wpisano nazwy!";
else
{
name = Nametb.Text;
Nametb.Clear();
Nametb.Enabled = false;
Namebt.Enabled = false;
Messageslb.Enabled = true;
timer1.Start();
LoopConnect();
}
}
private void LoopConnect()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
_clientSocket.Connect(IPAddress.Loopback, 100);
}
catch (SocketException)
{
Messageslb.Items.Clear();
Messageslb.Items.Add("Connection attempts: " + attempts.ToString());
Messageslb.Refresh();
}
}
Messageslb.Items.Add("Connected!");
Messageslb.Refresh();
Messagetb.Enabled = true;
Sendbt.Enabled = true;
}
private bool Test(string text)
{
if (text != "") return true;
return false;
}
private void Sendbt_Click(object sender, EventArgs e)
{
if (!Test(Messagetb.Text)) Messagetb.Text = "Nie wpisano zadnej wiadomosci!";
else
{
Send();
}
}
private void Receive()
{
if(_clientSocket.ReceiveBufferSize > 0)
{
byte[] receivedBuffer = new byte[1024];
int rec = _clientSocket.Receive(receivedBuffer);
byte[] data = new byte[rec];
Array.Copy(receivedBuffer, data, rec);
Messageslb.Items.Add(Encoding.ASCII.GetString(data));
}
}
private void Send()
{
string message = "[" + name + "]: " + Messagetb.Text;
Messagetb.Clear();
byte[] buffer = Encoding.ASCII.GetBytes(message);
_clientSocket.Send(buffer);
Receive();
}
private void Nametb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return) Namebt_Click(sender, e);
}
private void Messagetb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return) Sendbt_Click(sender, e);
}
private void timer1_Tick(object sender, EventArgs e)
{
Receive();
}
}
You need to run the receive method on a separate task.
_clientSocket.Receive(receivedBuffer);
should be:
private Task _receiving;
private void Receive()
{
if(_clientSocket.ReceiveBufferSize > 0)
{
if(_receiving == null || _receiving.IsCompleted)
_receiving = Task.Run(() =>
{
byte[] receivedBuffer = new byte[1024];
int rec = _clientSocket.Receive(receivedBuffer);
byte[] data = new byte[rec];
Array.Copy(receivedBuffer, data, rec);
Messageslb.Items.Add(Encoding.ASCII.GetString(data));
});
}
}
Otherwise clientSocket.Receive will hang your program.
You will want to make sure Messageslb is thread safe though, that will take further research.
If you're looking for real time communication look into RTC Client for C# https://msdn.microsoft.com/en-us/library/ms946701.aspx. Otherwise I would highly recommend Socket.IO since it is truly simple to use and set up with extremely fast rtc! https://socket.io/get-started/chat

C# Emgucv turn off webcam

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 {}
}
}

C# Launcher based on WebClient

I'm creating simple launcher for my other application and I need advise on logical part of the program. Launcher needs to check for connection, then check for file versions (from site), compare it with currently downloaded versions (if any) and if everything is alright, start the program, if not, update (download) files that differs from newest version. The files are:
program.exe, config.cfg and mapFolder. The program.exe and mapFolder must be updated, and config.cfg is only downloaded when there is no such file. Additionaly mapFolder is an folder which contains lots of random files (every new version can have totally different files in mapFolder).
For the file version I thought I would use simple DownloadString from my main site, which may contain something like program:6.0,map:2.3, so newest program ver is 6.0 and mapFolder is 2.3. Then I can use FileVersionInfo.GetVersionInfo to get the version of current program (if any) and include a file "version" into mapFolder to read current version.
The problem is I dont know how to download whole folder using WebClient and what's the best way to do what I want to do. I've tried to download the mapFolder as zip and then automatically unpack it, but the launcher need to be coded in .net 3.0.
Here is my current code, that's just a prototype to get familiar with whole situation, dont base on it.
`
WebClient wc = new WebClient();
string verifySite = "google.com/downloads/version";
string downloadSite = "google.com/downloads/program.exe";
Uri verifyUri, downloadUri = null;
string userVer, currVer = "";
string downloadPath = Directory.GetCurrentDirectory();
string clientName = "program.exe";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(FileDownloaded);
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(FileDownloadProgress);
chckAutorun.Checked = Properties.Settings.Default.autorun;
checkConnection();
if(!checkVersion())
downloadClient();
else
{
pbDownload.Value = 100;
btnPlay.Enabled = true;
lblProgress.Text = "updated";
if (chckAutorun.Checked)
btnPlay.PerformClick();
}
}
private bool checkConnection()
{
verifyUri = new Uri("http://" + verifySite);
downloadUri = new Uri("http://" + downloadSite);
WebRequest req = WebRequest.Create(verifyUri);
try
{
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
return true;
}
catch { }
verifyUri = new Uri("https://" + verifySite);
downloadUri = new Uri("https://" + downloadUri);
req = WebRequest.Create(verifyUri);
try
{
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
return true;
}
catch { }
return false;
}
private void downloadClient()
{
try
{
wc.DownloadFileAsync(downloadUri, Path.Combine(downloadPath, clientName));
}
catch { }
}
private bool checkVersion()
{
lblProgress.Text = "checking for updates";
try
{
currVer = FileVersionInfo.GetVersionInfo(Path.Combine(downloadPath, clientName)).FileVersion;
}
catch {
currVer = "";
}
try
{
userVer = wc.DownloadString(verifyUri);
}
catch {
userVer = "";
}
return currVer == userVer && currVer != "";
}
private void FileDownloaded(object sender, AsyncCompletedEventArgs e)
{
btnPlay.Enabled = true;
lblProgress.Text = "updated";
if (chckAutorun.Checked)
btnPlay.PerformClick();
}
private void FileDownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
long received = e.BytesReceived / 1000;
long toReceive = e.TotalBytesToReceive / 1000;
lblProgress.Text = string.Format("{0}KB {1}/ {2}KB", received, Repeat(" ", Math.Abs(-5 + Math.Min(5, received.ToString().Length))*2), toReceive);
pbDownload.Value = e.ProgressPercentage;
}
private void btnPlay_Click(object sender, EventArgs e)
{
btnPlay.Enabled = false;
if(checkVersion())
{
lblProgress.Text = "Starting...";
Process.Start(Path.Combine(downloadPath, clientName));
this.Close();
}
else
{
downloadClient();
}
}
public static string Repeat(string instr, int n)
{
if (string.IsNullOrEmpty(instr))
return instr;
var result = new StringBuilder(instr.Length * n);
return result.Insert(0, instr, n).ToString();
}
private void chckAutorun_CheckedChanged(object sender, EventArgs e)
{
Properties.Settings.Default.autorun = chckAutorun.Checked;
Properties.Settings.Default.Save();
}`
I've managed to achieve what I need by enabling autoindex on web server and download string of files in folder ending with .map .
string mapSite = wc.DownloadString(new Uri("http://" + mapsSite));
maps = Regex.Matches(mapSite, "<a href=\"(.*).map\">");
foreach (Match m in maps)
{
string mapName = m.Value.Remove(0, 9).Remove(m.Length - 11);
downloaded = false;
wc.DownloadFileAsync(new Uri("http://" + mapsSite + mapName), Path.Combine(downloadPath, #"mapFolder/" + mapName));
while (!downloaded) { }
}

Previous Page state lost on back key press

I am creating a Windows Phone 8.1 Universal App. There are some screens on my app. On the first screen, i am navigate my screen to second screen. When i press hardware back button on second screen. My previous page state lost.
I am unable to rectify where was the problem. Here is the code below:
Screen 1 Code
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedTo(e);
this.NavigationCacheMode = NavigationCacheMode.Enabled;
if (e.NavigationMode == NavigationMode.New)
{
BindQuickDateComboBox();
if (Frame.BackStack.Count > 0)
{
var lastPage = Frame.BackStack.Last().SourcePageType;
if (lastPage != null && lastPage.FullName == "Cryoserver.AppLogin")
{
Frame.BackStack.Clear();
}
}
}
}
async private void appBarSearch_Click(object sender, RoutedEventArgs e)
{
try
{
if (IsValidateForm())
{
ProgressBar.IsVisible = true;
cmdBarSearch.IsEnabled = false;
if (await conn.Table<SearchQuery>().CountAsync() > 0)
{
await conn.DropTableAsync<SearchQuery>();
await conn.CreateTableAsync<SearchQuery>();
}
var searchTerms = new SearchQuery();
if (Convert.ToString(cmbQuickDate.SelectedItem) != "Any Date")
{
searchTerms.FromDate = pickerFromDate.Date.ToString("d MMM yyyy");
searchTerms.FromTime = pickerFromTime.Time.ToString();
searchTerms.ToDate = pickerToDate.Date.ToString("d MMM yyyy");
searchTerms.ToTime = pickerToTime.Time.ToString();
}
searchTerms.SearchKeywords = txtKeywords.Text;
searchTerms.Parties = txtParties.Text;
searchTerms.Contributer = txtFrom.Text;
searchTerms.Viewer = txtTo.Text;
searchTerms.AttachmentName = txtAttName.Text;
searchTerms.AttachmentKeywords = txtAttKeywords.Text;
searchTerms.SearchReason = txtSearchReason.Text;
searchTerms.IsHighLight = "false";
await conn.InsertAsync(searchTerms);
object resultMails = await SearchEmailArchive();
if (!String.IsNullOrEmpty(Convert.ToString(resultMails)))
{
GlobalInfo.SelectedRow = -1;
GlobalInfo.SearchPageIndex = -1;
GlobalInfo.IsFindKeyword = false;
var archiveMails = JsonConvert.DeserializeObject<SearchResult>(resultMails.ToString());
Frame.Navigate(typeof(MailList), archiveMails);
}
ProgressBar.IsVisible = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
ProgressBar.IsVisible = false;
}
cmdBarSearch.IsEnabled = true;
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
}
Screen 2
I too used this code in second screen and also after removing this code. But it didn't work for me. Still the same problem.
void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
if (Frame.CanGoBack)
{
e.Handled = true;
Frame.GoBack();
}
}
Screen 1 state is Blank and behaves as a freshly loaded screen. Why?
Any help would be much appreciated.
I would try setting NavigationCacheMode="Required" in the constructor/XAML instead.

Why this application is taking so much of memory?

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.

Categories