I have a page which is fetching data from a webservice using async call.
If i get the response from webservice control goes to catch where a message box is pooped.
The code is given below:
string uri = "http://free.worldweatheronline.com/feed/weather.ashx?key=b7d3b5ed25080109113008&q=Mumbai&num_of_days=5";
UriBuilder fullUri = new UriBuilder("http://free.worldweatheronline.com/feed/weather.ashx");
fullUri.Query = "key=b7d3b5ed25080109113008&q=Mumbai&num_of_days=5";
HttpWebRequest forecastRequest = (HttpWebRequest)WebRequest.Create(fullUri.Uri);
// set up the state object for the async request
ForecastUpdateState forecastState = new ForecastUpdateState();
forecastState.AsyncRequest = forecastRequest;
// start the asynchronous request
forecastRequest.BeginGetResponse(new AsyncCallback(HandleForecastResponse), forecastState);
This part is response
private void HandleForecastResponse(IAsyncResult asyncResult)
{
try
{
// get the state information
ForecastUpdateState forecastState = (ForecastUpdateState)asyncResult.AsyncState;
HttpWebRequest forecastRequest = (HttpWebRequest)forecastState.AsyncRequest;
// end the async request
forecastState.AsyncResponse = (HttpWebResponse)forecastRequest.EndGetResponse(asyncResult);
Stream streamResult;
string newCityName = "";
//int newHeight = 0;
// get the stream containing the response from the async call
streamResult = forecastState.AsyncResponse.GetResponseStream();
// load the XML
XElement xmlWeather = XElement.Load(streamResult);
}
catch (Exception ex)
{
MessageBox.Show("Connection Error");
}
}
Problem :
when the page is loaded it starts fetching data from webservice(consider the case when the web service is not responding and control goes to catch part).
In the mean time if we press the back button or navigate the page the message box popps on the new page.
How could i stop that.
Thanks and Regards
Haven't tested it, but it may work:
1/ Store the value of the NavigationService.CurrentSource property somewhere it can be retrieved (the best would be in the asyncState parameter, but a property may work as well
2/ In the HandleForecastResponse, compare the old and new value of the NavigationService.CurrentSource. This way, you should be able to deduce if the active page has changed or not.
ifixed that problem by add
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
});
try this
private void HandleForecastResponse(IAsyncResult asyncResult)
{
try
{
// get the state information
ForecastUpdateState forecastState = (ForecastUpdateState)asyncResult.AsyncState;
HttpWebRequest forecastRequest = (HttpWebRequest)forecastState.AsyncRequest;
// end the async request
forecastState.AsyncResponse = (HttpWebResponse)forecastRequest.EndGetResponse(asyncResult);
Stream streamResult;
string newCityName = "";
//int newHeight = 0;
// get the stream containing the response from the async call
streamResult = forecastState.AsyncResponse.GetResponseStream();
// load the XML
XElement xmlWeather = XElement.Load(streamResult);
}
catch (Exception ex)
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Connection Error");
});
}
}
Finally solved it.
catch (Exception x)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
var currentPage = ((App)Application.Current).RootFrame.Content as PhoneApplicationPage;
if ((currentPage.ToString()).Equals("MumbaiMarathon.Info.News"))
{
MessageBox.Show("Connection Error");
}
});
}
I just checked at the time of popping the message box the name of the Current UI application page. If its same as the page from which message box is initiated than it pops otherwise not.
Related
I'm working on a project to display the information received from the API in a DataGridView. I have created a Thread to update the DataGridView that runs the DataGridView refresh method every 5 seconds in a parallel process. But when the program runs, after one step of the Thread, the information is placed in the DataGridView, I get this error in the second step of calling the "RefreshGridData" function by Thread:
exception {"Object reference not set to an instance of an object."} System.NullReferenceException
Here are the codes of the Thread and the DataGridView refresh function called by that:
Data Refreshing Thread
{
trdRefresh = new Thread(() =>
{
while (true)
{
try
{
RefreshGridData();
Thread.Sleep(1000 * 5);
}
catch (Exception ex)
{
Thread.Sleep(1000 * 5);
}
}
});
trdRefresh.Start();
}
RefreshGridData:
var response = DataReceiver();
var data = JsonConvert.DeserializeObject<List<ClientPulsLog>>(response);
var source = new BindingSource
{
DataSource = Data
};
DataGridView1.DataSource = source; //The error occurs here
DataGridView1.Refresh();
Data Receiver:
public static string DataReceiver()
{
try
{
using (var client = new HttpClient())
{
var url = $"http://{"127.0.0.1:9094"}/DataProvider/TotalData/";
var request = "{\"MessageType\":"+ typeId + "}";
var content = client.GetAsync(url).GetAwaiter().GetResult().Content.ReadAsStringAsync().GetAwaiter().GetResult();
return content;
}
}
catch
{
}
return string.Empty;
}
Important note
The interesting thing is that when I put a Watch Point at the beginning of the error line, whenever it arrives and pauses while debugging, if I wait a second and then click on the Continue button, the program will continue without any problems.
How can I solve this problem?
Thanks.
Im working on an EConnect integration Windows form app in C#. Im having a lot of trouble testing my connection string. Basically I give the user the option to change the connection string so I want to be able to test it. As far as I know EConnect doesnt have any built in functions that test the connection so I'm writing a pretty crude function to do it myself. Just for everyones information the connection string consists of a server name that the GP databases are located on and a database name.
The particulars of the actual test function I dont think are that important but the main issue is within that function I call an eConnect method called getEntity, this method uses the connection string and if the connection string is right it will pull information. If the database name is wrong the getEntity method will return an eConnect exception which is easy enough to catch, however if the server name is wrong the getEntity method will just spin and my app gets stuck.
Im trying to write something where I can possibly run my test function asynchronously and simultaneously check for a timeout or the econnect exception. This is where I get stuck, I cant for the life of me get it to work. Here is the first thing I tried (this is in my TestConnection method):
task = Task.Factory.StartNew(() => requester.GetEntity(GPCongfigSettings.GPConnectionString, myXmlDocument.OuterXml), token);
try
{
if (!task.Wait(timeOut, token))
{
Console.WriteLine("The server name is incorrect - task timed out");
return false;
}
}
catch (ThreadInterruptedException)
{
return false;
}
catch (AggregateException ae)
{
ae.Handle((x) =>
{
if (x is eConnectException) // This we know how to handle.
{
Console.WriteLine("Incorrect Database Name! -- " + x.Message);
return false;
}
return false; // Let anything else stop the application.
});
}
This would catch the cases where the server was wrong and if my econnect method would just time out. But it never caught the eConnect exception, Visual Studio would break the app and tell me I had an unhandled exception.
Here is what Im trying now, this is the full class I have for my form. Here I'm trying to use IAsyncResult and using a WaitHandle to check to see if the function completes or times out. This seems to work sometimes, it works for a correct string and for when the database is wrong, and sometimes it works for when the server is wrong, but once I test for a wrong server name it doesnt work correctly for anything else anymore. Is there something I'm missing or is there a better way to run the getentity method in TestGPConnection and check to see if it hasnt completed after a certain time period and if it hasnt kill that method and have the user reenter a server name?
public partial class UpdateGPConnection : Form
{
Task task;
AsyncCallback cb;
public delegate string startProcessToCall();
startProcessToCall sp2c;
public UpdateGPConnection()
{
InitializeComponent();
this.txtDatasourceName.Text = ConfigurationManager.AppSettings.Get("GPDataServer");
this.txtDatabaseName.Text = ConfigurationManager.AppSettings.Get("GPDatabase");
cb = new AsyncCallback(startProcessCallback);
sp2c = new startProcessToCall(TestGPConnection);
}
public void startProcessCallback(IAsyncResult iar)
{
startProcessToCall mc = (startProcessToCall)iar.AsyncState;
bool result = mc.EndInvoke(iar);
Console.WriteLine("Function value = {0}", result);
}
private void btnUpdate_Click(object sender, EventArgs e)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["GPDataServer"].Value = txtDatasourceName.Text.ToUpper();
config.AppSettings.Settings["GPDatabase"].Value = txtDatabaseName.Text.ToUpper();
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
GPCongfigSettings.GPConnectionString = #"data source=" + txtDatasourceName.Text.ToUpper() + ";initial catalog=" + txtDatabaseName.Text.ToUpper() + ";integrated security=SSPI;persist security info=False;packet size=4096";
IAsyncResult asyncResult = null;
asyncResult = sp2c.BeginInvoke(cb, null);
timer1.Enabled = true;
Thread.Sleep(0);
bool test = asyncResult.AsyncWaitHandle.WaitOne(15000);
if (test)
{
try
{
string testResult = sp2c.EndInvoke(asyncResult);
}
catch (Exception exc)
{
Console.WriteLine(exc.Message);
}
}
bool result = asyncResult.IsCompleted;
asyncResult.AsyncWaitHandle.Close();
this.Close();
}
public string TestGPConnection()
{
eConnectMethods requester = new eConnectMethods();
try
{
// Create an eConnect document type object
eConnectType myEConnectType = new eConnectType();
// Create a RQeConnectOutType schema object
RQeConnectOutType myReqType = new RQeConnectOutType();
// Create an eConnectOut XML node object
eConnectOut myeConnectOut = new eConnectOut();
// Populate the eConnectOut XML node elements
myeConnectOut.ACTION = 1;
myeConnectOut.DOCTYPE = "GL_Accounts";
myeConnectOut.OUTPUTTYPE = 2;
myeConnectOut.FORLIST = 1;
myeConnectOut.WhereClause = "(ACTNUMST = '99-9999-99-999')";
// Add the eConnectOut XML node object to the RQeConnectOutType schema object
myReqType.eConnectOut = myeConnectOut;
// Add the RQeConnectOutType schema object to the eConnect document object
RQeConnectOutType[] myReqOutType = { myReqType };
myEConnectType.RQeConnectOutType = myReqOutType;
// Serialize the eConnect document object to a memory stream
MemoryStream myMemStream = new MemoryStream();
XmlSerializer mySerializer = new XmlSerializer(myEConnectType.GetType());
mySerializer.Serialize(myMemStream, myEConnectType);
myMemStream.Position = 0;
// Load the serialized eConnect document object into an XML document object
XmlTextReader xmlreader = new XmlTextReader(myMemStream);
XmlDocument myXmlDocument = new XmlDocument();
myXmlDocument.Load(xmlreader);
string reqDoc = requester.GetEntity(GPCongfigSettings.GPConnectionString, myXmlDocument.OuterXml);
return "Correct Connection";
}
catch (eConnectException exc)
{
Console.WriteLine(exc.Message);
return "eConnect Excpetion";
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return "Excpetion";
}
}
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
}
You are not handling the eConnectException. You are showing a message in the Console and then essentially rethrowing the exception by returning false.
If you do handle an exception then you should return true to avoid rethrowing it:
catch (AggregateException ae)
{
ae.Handle((x) =>
{
if (x is eConnectException) // This we know how to handle.
{
Console.WriteLine("Incorrect Database Name! -- " + x.Message);
}
return x is eConnectException; //rethrow anything that is not an eConnectException
});
}
Recently, I found that Windows Phone Background Transfer Service seems to have memory leak issue.
Every background transfer you add will take a memory space, which cannot be removed by GC forever.
I already read through http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202959(v=vs.105).aspx , and still have no idea where the memory leak comes from.
What I test is very simple, add a background transfer request to the BackgroundTransferService and when that request is complete, remove it from BackgroundTransferService and add another one. If I keep doing it, I'll see the memory grows even when GC.collect being called every sec. Please download the testing code in http://hdtp.synology.me/BTS.zip and you'll know what I'm saying. The following is the testing code summary.
private int _transferCount = 1000;
private void CreateTask()
{
if (--_transferCount < 0)
{
MessageBox.Show("End");
return;
}
// Get the URI of the file to be transferred from the Tag property
// of the button that was clicked.
//string transferFileName = ((Button)sender).Tag as string;
string transferFileName = "http://hdtp.synology.me/a.jpg";
Uri transferUri = new Uri(Uri.EscapeUriString(transferFileName + "?ranNum=" + _transferCount), UriKind.RelativeOrAbsolute);
// Create the new transfer request, passing in the URI of the file to
// be transferred.
BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(transferUri);
// Set the transfer method. GET and POST are supported.
transferRequest.Method = "GET";
// Get the file name from the end of the transfer Uri and create a local Uri
// in the "transfers" directory in isolated storage.
string downloadFile = transferFileName.Substring(transferFileName.LastIndexOf("/") + 1);
Uri downloadUri = new Uri("shared/transfers/" + downloadFile, UriKind.RelativeOrAbsolute);
transferRequest.DownloadLocation = downloadUri;
// Pass custom data with the Tag property. This value cannot be more than 4000 characters.
// In this example, the friendly name for the file is passed.
transferRequest.Tag = downloadFile;
// Add the transfer request using the BackgroundTransferService. Do this in
// a try block in case an exception is thrown.
try
{
BackgroundTransferService.Add(transferRequest);
}
catch (InvalidOperationException ex)
{
// TBD - update when exceptions are finalized
MessageBox.Show("Unable to add background transfer request. " + ex.Message);
}
catch (Exception)
{
MessageBox.Show("Unable to add background transfer request.");
}
InitialTansferStatusCheck();
}
private void InitialTansferStatusCheck()
{
UpdateRequestsList();
foreach (var transfer in transferRequests)
{
transfer.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferStatusChanged);
ProcessTransfer(transfer);
}
}
private void transfer_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
{
ProcessTransfer(e.Request);
}
private void UpdateRequestsList()
{
// The Requests property returns new references, so make sure that
// you dispose of the old references to avoid memory leaks.
if (transferRequests != null)
{
foreach (var request in transferRequests)
{
request.Dispose();
}
}
transferRequests = BackgroundTransferService.Requests;
}
private void ProcessTransfer(BackgroundTransferRequest transfer)
{
switch (transfer.TransferStatus)
{
case TransferStatus.Completed:
// If the status code of a completed transfer is 200 or 206, the
// transfer was successful
if (transfer.StatusCode == 200 || transfer.StatusCode == 206)
{
// Remove the transfer request in order to make room in the
// queue for more transfers. Transfers are not automatically
// removed by the system.
RemoveTransferRequest(transfer.RequestId);
// In this example, the downloaded file is moved into the root
// Isolated Storage directory
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
string filename = transfer.Tag;
if (isoStore.FileExists(filename))
{
isoStore.DeleteFile(filename);
}
isoStore.MoveFile(transfer.DownloadLocation.OriginalString, filename);
}
CreateTask();
}
else
{
// This is where you can handle whatever error is indicated by the
// StatusCode and then remove the transfer from the queue.
RemoveTransferRequest(transfer.RequestId);
if (transfer.TransferError != null)
{
// Handle TransferError, if there is one.
}
}
break;
}
}
private void RemoveTransferRequest(string transferID)
{
// Use Find to retrieve the transfer request with the specified ID.
BackgroundTransferRequest transferToRemove = BackgroundTransferService.Find(transferID);
// try to remove the transfer from the background transfer service.
try
{
BackgroundTransferService.Remove(transferToRemove);
}
catch (Exception ex)
{
}
}
Another few questions, according to the documentation above, we'll get the new instance from BackgroundTransferService.Requests every time, but if I called GetHashCode(), I get the same hash code every time and the hash code is even the same with the one I newed and added into BackgroundTransferService. So is it because MS override the GetHashCode method of BackgroundTransferRequest? or I misunderstand something. But in the sample code above, I did not use BackgroundTransferService.Requests to get any instance, the memory still keep growing.
Please tell me what I do wrong or any workaround, thanks...
So in my app I have a button that talks to a lib that downloads some data from the internet and filters it. When the app is doing this the screen freezes and it looks to the user like the app crashed. But this is not the case because its downloading data.
Here is my code:
GetDetailsBtn.TouchUpInside += (sender, e) => {
var defaults = NSUserDefaults.StandardUserDefaults;
if (RefNr.Text != string.Empty && RefNr.Text != null) {
FilteredDataRef = _FetchingData.getTrackTraceData (defaults.StringForKey ("SecurityToken"), RefNr.Text);
if (FilteredDataRef == null) {
UIAlertView InvalidAlert = new UIAlertView ("Reference number invalid", "The reference number that you have entered is not linked to the current security code. You can change your security code in the settings.", null, "OK", null);
InvalidAlert.Show ();
} else {
FilteredDataReceived = _FetchingData.FilteringOnReceived (FilteredDataRef);
FilteredDataPlanned = _FetchingData.FilteringOnPlanned (FilteredDataRef);
FilteredDataLoadingETA = _FetchingData.FilteringOnLoadingETA (FilteredDataRef);
FilteredDataLoadingFinal = _FetchingData.FilteringOnLoadingFinal (FilteredDataRef);
FilteredDataUnloadingETA = _FetchingData.FilteringOnUnloadingETA (FilteredDataRef);
FilteredDataUnloadingFinal = _FetchingData.FilteringOnUnloadingFinal (FilteredDataRef);
this.PerformSegue (MoveToTrackTraceDetailsSegue, this);
//foreach (string s in FilteredDataPlanned)
// Console.WriteLine (s);
}
} else {
UIAlertView InvalidAlert = new UIAlertView ("Reference number cannot be empty", "You did not provide a reference number. We need your reference number to trace identify the shipment you would like to trace.", null, "OK", null);
InvalidAlert.Show ();
}
};
Downloading of the data:
public IEnumerable<string> getTrackTraceData (string securityCode, string referenceNumber)
{
WebRequest request = WebRequest.Create ("http://plex.janssen1877.com/app/life/" + securityCode);
HttpWebResponse response = (HttpWebResponse)request.GetResponse ();
Stream dataStream = response.GetResponseStream ();
StreamReader reader = new StreamReader (dataStream);
string FetchedData = reader.ReadToEnd ();
reader.Close ();
dataStream.Close ();
response.Close ();
var FetchingDataItems = FetchedData.Split (new char[] { '\n' });
if (FetchingDataItems != null) {
var filteredResult = FetchingDataItems.Where (x => x.Contains (referenceNumber));
return filteredResult;
} else {
return null;
}
}
Now I want to use a component called BTProgressHUD. This is just a fancy spinner. I thought that if I would put BTProgressHUD.show(); to the top of the button action and BTProgressHUD.Dismiss(); to the button it would show when the loading starts and dismiss when its done loading.
This is not the case. It shows very quickly in the new view controller and dismisses again within a second. What am I doing wrong?
Edit for exemple:
public IEnumerable<string> getTrackTraceData (string securityCode, string referenceNumber)
{
string url = string.Format ("http://plex.janssen1877.com/app/life/" + securityCode);
HttpWebRequest HttpRequest = (HttpWebRequest)WebRequest.Create (url);
string FetchedData = new StreamReader (HttpRequest.GetResponse ().GetResponseStream ()).ReadToEnd ();
var FetchingDataItems = FetchedData.Split (new char[] { '\n' });
if (FetchingDataItems != null) {
var filteredResult = FetchingDataItems.Where (x => x.Contains (referenceNumber));
return filteredResult;
} else {
return null;
}
}
Florian,
According to .NET documentation and HttpWebRequest GetResponse. How to wait for that response? you need to perform the download (and maybe the parsing) in a async fashion.
The behavior of your actual application is correct. When you perform a sync request in the main thread you freeze the application and hence the UI elements are not updated. The main thread processes execution in a serial fashion.
To avoid this you have two different solutions. On the one hand, you need to move to an async request. On the other hand, you can create a background thread (a different path of execution) with a sync request. I prefer the former. So, for example, after starting the async request, show the indicator. When you have finished (in the callback), dismiss the indicator and perform the segue.
For example, you can follow the following discussion on how to achieve this: How to use HttpWebRequest (.NET) asynchronously?.
To understand how the main thread (and the run loop) works, I suggest to read about The pogo stick of NSRunLoop.
Hope that helps.
Edit
You should use a pattern like the following (source How to use HttpWebRequest (.NET) asynchronously?):
HttpWebRequest webRequest;
void StartWebRequest()
{
webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
}
void FinishWebRequest(IAsyncResult result)
{
webRequest.EndGetResponse(result);
}
It sounds like you're attempting to do all this in the same thread as your UI, which is why your app freezes and waits for processing to finish without showing anything. I would perform this download operation in a backgroundworker of some sort. Then I am not sure in Mono but access the main thread before and after and show and dismiss your loading component.
I am using Waitin RC2, WatiN-2.0.20.1089, Windows XP OS with IE8 With VS2008 and NUnit-2.5.7.10213. I have added the sites to the trusted list, I have thread sleeps, I have tried "WaitForComplete". yet when the script goes "back" I am still getting an unauthorized access exception.
Here is a chunk of my code, the exceptions are never caught inspite of the fact that most of the code is in try catch blocks.
public string FindAllLinks()
{
/*
* This function is designed to find and use all of the links on a given page.
* After clicking on a link it waits for 400 milliseconds on the page so the page
* has some time to load and then the function "hits the back button" reseting
* to the originating page.
* This function is not meant to be recursive.
*/
string message = "";
bool flag = true;
//Get a list of all links from the browser instance
foreach (Link link in browserInstance.Links)
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine(link);
try
{//clicking on the link to make sure it leads somewhere
link.Click(); //If the click fails hopefull we will thrwo out of the try block and not execute the next two commands.
//Console.WriteLine(link);
}
catch (Exception)
{//OOPs we have an error let's log a message.
message = message + "The link titled " + link + " was not found, or did not work.\n";
flag = false;
}
if (flag)
{
System.Threading.Thread.Sleep(1000);
//browserInstance.WaitForComplete;
try { browserInstance.Back(); }
catch (UnauthorizedAccessException)
{
//do nothing
}
}//close if flag
}//close for each
//return the message
return (message);
}//Close function
[STAThread]
[Test]
public void TestTitleHomePage()
{
bool testPassed = false;
if (browserInstance.Title.Contains("<title>"))
{
string message = FindAllLinks();
if (message == "") { testPassed = true; }
}//close if
else { message = "The Title was not the same."; }
Assert.IsTrue(testPassed, message);
}// end TestTitleHomePage
I tried your code and I also get the exception. I think I understand what happens. When you first do Browser.Links, you get all the links of the current page, then you navigate to another page and return to the first page, but for WatiN it is a new page. So your enumeration cannot work because you enumerate though the links of the first page.
What I suggest you could do is to get all the Uri of the links, then try them one by one in a new browser
IEnumerable<Uri> uris = Browser.Links.Select(l => l.Uri);
foreach(Uri uri in Uris)
{
try
{
using(var browser = new IE(uri))
{
// do nothing or detect 404, 403, etc errors
}
// no error
}
catch(exception)
{
// log error
}
}