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.
Related
I'm using the ZXing plugin to scan bar codes and I'm using a custom overlay to display information and make a button visible/invisible when I need to perform an action, which in this case is to set a flag and make the button invisible again.
In this code I set up the scanning plugin:
MyButton_Scan.Click += async (sender, e) =>
{
var selectedEvent = string.Format("{0}", MyEventsSpinner.GetItemAtPosition(MyEventsSpinner.SelectedItemPosition));
if (selectedEvent.ToUpper() != "SELECT EVENT")
{
MobileBarcodeScanner.Initialize(Application);
scanner = new MobileBarcodeScanner();
scanner.UseCustomOverlay = true;
zxingOverlay = LayoutInflater.FromContext(this).Inflate(Resource.Layout.scanner, null);
MyScanScreenButton = zxingOverlay.FindViewById<Android.Widget.Button>(Resource.Id.okButton);
MyScanScreenButton.Click += btnOk_Click;
MyScanScreenButton.Visibility = Android.Views.ViewStates.Invisible;
scanner.CustomOverlay = zxingOverlay;
var opt = new MobileBarcodeScanningOptions();
opt.DelayBetweenContinuousScans = 5000;
//Start scanning
scanner.ScanContinuously(this, opt, HandleScanResult);
} else
{
Utils.showMessage("Please select an event from the drop down list");
}
};
The code that handles the scan result and button click:
void btnOk_Click(object sender, System.EventArgs e)
{
popUpOpen = false;
MyScanScreenButton.Visibility = Android.Views.ViewStates.Invisible;
}
void HandleScanResult(ZXing.Result result)
{
if (!popUpOpen)
{
Boolean ConversionGood = true;
TextView MyTextView = zxingOverlay.FindViewById<TextView>(Resource.Id.ticketInfo);
Int32 convertedResult = 0;
Stream successbeepStream = GetType().Assembly.GetManifestResourceStream("eTicket_Scanner.beep.wav");
Stream failbeepStream = GetType().Assembly.GetManifestResourceStream("eTicket_Scanner.buzzer.wav");
MyTextView.SetBackgroundColor(Color.White);
try
{
convertedResult = Convert.ToInt32(result.Text);
}
catch (Exception ex)
{
ConversionGood = false;
bool isSuccess = _simpleAudioPlayer.Load(failbeepStream);
_simpleAudioPlayer.Play();
popUpOpen = true;
MyScanScreenButton.Visibility = Android.Views.ViewStates.Visible;
MyTextView.SetBackgroundColor(Color.Red );
MyTextView.Text = "Not a valid ticket for this event.\nErrorif applicable): " + ex.Message;
}
string scanResult = "";
if (ConversionGood)
{
scanResult = MyEventsService.VerifyScannedCode(MyUser.Username, MyUser.Password, currentEventID, convertedResult);
if (scanResult == "Y")
{
MyTextView.SetBackgroundColor(Color.Green);
bool isSuccess = _simpleAudioPlayer.Load(successbeepStream);
popUpOpen = true;
MyTextView.SetBackgroundColor(Color.Green);
MyTextView.Text = MyEventsService.GetTicketInfo(MyUser.Username, MyUser.Password, currentEventID, convertedResult);
_simpleAudioPlayer.Play();
MyScanScreenButton.Visibility = Android.Views.ViewStates.Visible;
}
else
{
bool isSuccess = _simpleAudioPlayer.Load(failbeepStream);
popUpOpen = true;
MyTextView.SetBackgroundColor(Color.Red);
MyTextView.Text = MyEventsService.GetFailedScanTicketInfo(MyUser.Username, MyUser.Password, currentEventID, convertedResult);
_simpleAudioPlayer.Play();
MyScanScreenButton.Visibility = Android.Views.ViewStates.Visible;
}
}
}
}
Its not a very complicated app, scan barcodes and verify the code, set the color of the textview background and display the info. The "Ok" button is never visible, but if I click in the space where the button should appear, it executes the button click code. I'm assuming that there is some sort of thread issue here with the interface, but anything I've tried with the thread hasn't worked. Anyone have any ideas?
I have an active Google Places autocomplete working with Xamarin Forms or Cross Platform. I have a working solution that auto populates the address when the user types in the address. My problem is when the user selects it from the list the address does not go to the search_bar.text… The search bar just remains with the text that was typed? how can I get the text when selected to populate in the search bar.
I am new to Xamarin forms and C#.
public Createbusinessaccount ()
{
InitializeComponent ();
search_bar.ApiKey = GooglePlacesApiKey;
search_bar.Type = PlaceType.Address;
search_bar.Components = new Components("country:us"); // Restrict results to Australia and New Zealand
search_bar.PlacesRetrieved += Search_Bar_PlacesRetrieved;
search_bar.TextChanged += Search_Bar_TextChanged;
search_bar.MinimumSearchText = 2;
results_list.ItemSelected += Results_List_ItemSelected;
}
void Search_Bar_PlacesRetrieved(object sender, AutoCompleteResult result)
{
results_list.ItemsSource = result.AutoCompletePlaces;
spinner.IsRunning = false;
spinner.IsVisible = false;
if (result.AutoCompletePlaces != null && result.AutoCompletePlaces.Count > 0)
results_list.IsVisible = true;
}
void Search_Bar_TextChanged(object sender, TextChangedEventArgs e)
{
if (!string.IsNullOrEmpty(e.NewTextValue))
{
results_list.IsVisible = false;
spinner.IsVisible = true;
spinner.IsRunning = true;
}
else
{
results_list.IsVisible = true;
spinner.IsRunning = false;
spinner.IsVisible = false;
}
}
async void Results_List_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
return;
var prediction = (AutoCompletePrediction)e.SelectedItem;
results_list.SelectedItem = null;
var place = await Places.GetPlace(prediction.Place_ID, GooglePlacesApiKey);
if (place != null)
await DisplayAlert(
place.Name, string.Format("Lat: {0}\nLon: {1}", place.Latitude, place.Longitude), "OK");
}
In your ItemSelected method, you need to set the text of the searchbar:
async void Results_List_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
return;
var prediction = (AutoCompletePrediction)e.SelectedItem;
search_bar.Text = prediction.Name? // Your property here
results_list.SelectedItem = null;
var place = await Places.GetPlace(prediction.Place_ID, GooglePlacesApiKey);
if (place != null)
await DisplayAlert(
place.Name, string.Format("Lat: {0}\nLon: {1}", place.Latitude, place.Longitude), "OK");
}
I am still trying to fix this, it only adds the street name and number not the whole address
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 {}
}
}
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.
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.