I've built a simple app that talks over UDP, to an endpoint at an IP the user specifies. It uses System.Net.Sockets.UdpClient, which works pretty well on Android - I'm able to send and receive packets fairly consistently. With one glaring exception... Exceptions. It seems to completely evade try/catch; my guess is the underlying implementation errors so hard that errors cannot be caught. For example:
UdpClient Udp { get; protected set; }
Udp.Connect("192.168.1.254"); // Any bad IP
try
{
int bytesSent = await udp.SendAsync(bytes, bytes.Length);
}
catch(Exception ex)
{
return null;
}
When testing on an actual Android device, any UDP traffic sent to a bad IP consistently destroys the application.
The behavior gets crazier. For example, if I put the call out on a background thread, with a nested try/catch, like this:
Task.Run(ping).ConfigureAwait(false);
protected async Task ping()
{
try
{
await checkIp();
}
catch(Exception ex)
{
}
}
Then there are some scenarios where I actually can get an Exception - but only in the outer catch! The throw occurs on the SendAsync call inside the inner try, but the inner catch misses it, landing only in the outer catch. The exception is a System.Net.Sockets.SocketException with type ConnectionRefused. Depending on how exactly I step through it, sometimes that gets caught there, sometimes not at all; when it's not at all, the app just implodes.
Is this expected behavior? Is Xamarin UdpClient just not supposed to be used? Bug? Better approach than SendAsync? Other?
Related
We're using PushStreamContent to stream some large lumps with Content-Disposition headers set and the like. As a number of people have discovered, the drawback is what happens when something goes wrong in the streaming?
At the very least, we were trying to get the error logged on our side so someone could follow up.
Recently, I ran into a weird situation. Putting a try/catch around the streaming function worked well enough for errors encountered before you actually started streaming (i.e. errors in sql queries and the like), but if the error occurred later (like in the serialization), the catch block doesn't fire.
Would anyone have any idea why that is?
e.g.
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
try
{
response.Content = new PushStreamContent((stream, content, context) =>
{
using (XmlWriter rWriter = PrepForXmlOutput(stream))
{
rpt.GenerateXmlReport(rWriter, reportParams, true);
}
}, "EventReport", extension);
}
catch (Exception e)
{
// The first step of GenerateXmlReport() is to run the sql;
// if the error happens there, this fires and will log the exception
// if the error happens later, during the result serialization, this does NOT fire
Log.Error(e);
}
return response;
Hate it when I see the answer just after I hit Post.
Try/catch around the outside only covers until I return the HttpResponseMessage. When/where I get the exception depends on how far the inner method gets before that return happens.
The try/catch needed to be on the inner call (the one where all the work happens) to cover the whole lifecycle.
I am developing an app using Xamarin.Forms to re-use as much code as possible.
Specifically, I have a static class that manages all the POST/GET requests to my Azure Web Server.
Everything single call works fantastically except for one call - this one:
public async static Task<Models.UserParkPosition> GetUserParkPositionForCurrentUserAsync()
{
var body = new JArray { App.User.Id };
var test = await AzureMobileServiceClient.Instance.MobileService.InvokeApiAsync<JArray, Models.UserParkPosition>(ConnectionsAPI, body, HttpMethod.Get, null);
return test;
}
The method above is called when the user presses a button - specifically like this:
private async Task OnGoingToTheParkClicked(object sender, EventArgs e)
{
bool success = false;
var already = await viewModel.AlreadyHavePendingRequestAsync());
Console.WriteLine("TEST");
throw new Exception();
}
When the debugger hits the "var test" line mentioned, above.... nothing happens. The code doesn't deadlock, the UI is still responsive, but the code never returns. I never see the "TEST" word and the exception is not even thrown... what happens??
All my other APIs are called in the same way, and are working correctly.
OTHER INFO:
- Same code works on UWP and Android
- The GET request arrives at the webservice, which responds in a timely fashion (< 1 sec)
Thanks to anyone who might help or even point me in the right direction!
Found the issue - InvokeApiAsync throws an exception which is not catched anywhere from any calling thread. It somehow just disappears without causing any error nor device log, nor crash. Weird, but that's how the world goes.
I am trying to fetch Customer data to parse them into customer object to display on TableView. The following code sometimes works, sometimes not. Whenever it does crash, it shows Customer data is empty in the foreach loop even though I run the same code every time. I do not have clue what could be wrong in this circumstances. I am quite new on this platform. If I am missing anything/ extra information, please let me know.
namespace TableViewExample
{
public partial class MyDataServices : ContentPage
{
private ODataClient mODataClient;
private IEnumerable <IDictionary<string,object>> Customers;
public MyDataServices ()
{
InitializeComponent ();
InitializeDataService ();
GetDataFromOdataService ();
TableView tableView = new TableView{ };
var section = new TableSection ("Customer");
foreach (var customers in Customers) {
//System.Diagnostics.Debug.WriteLine ((string)customers ["ContactName"]);
var name = (string)customers ["ContactName"];
var cell = new TextCell{ Text = name };
section.Add (cell);
}
tableView.Root.Add (section);
Padding = new Thickness (10, 20, 10, 10);
Content = new StackLayout () {
Children = { tableView }
};
}
private void InitializeDataService(){
try {
mODataClient = new ODataClient ("myURL is here");
}
catch {
System.Diagnostics.Debug.WriteLine("ERROR!");
}
}
private void GetDataFromOdataService (){
try {
Customers = mODataClient.For ("Customers").FindEntries ();
}
catch {
System.Diagnostics.Debug.WriteLine("ERROR!");
}
}
}
}
Its hard helping out here, however here are some things to consider:-
It sounds like the dataservice could either be not contactable / offline; too busy or it could even be throwing an exception itself and returning a data response that you are not expecting to receive, that then triggers an exception and crash in your application as your always expecting an exact response without catering for any abnormal responses / events.
If you are contacting an external service over the internet it may just be your internet connection is slow / faulty and not returning the information fast enough as other possibilities.
In your code you are assuming that you always get a response from the server - and that this response will always be of an anticipated structure that your expecting to decode - without factoring in any possibility of abnormal responses returned by the dataservice. I have not used ODataClient personally, so not sure how it behaves in the event of maybe no data received / timeout or in your case the dataservice and how it behaves internally in the response to a bad-request etc.
I am assuming an exception would get thrown, and you do get your debug line executed indicating a failure.
You may want to also adjust this statement so that you write out the exception as well, i.e.:-
private void GetDataFromOdataService ()
{
try
{
Customers = mODataClient.For ("Customers").FindEntries ();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("ERROR!" + ex.ToString());
}
}
If there was a bad response, then the line at Customers = ..... would throw the exception as there may be no Customers returned or some other information packaged in the response from the dataservice.
The Customers variable would also be null at this point I am assuming due to this failing.
So when you get back to your code at foreach (var customers in Customers) { it will then throw a null reference exception as Customers is infact null.
As all your current code executes in the constructor without any try and catch block around this, it will also crash your application at this point as well.
Also you are doing all of this work in the constructor. Try seperating this out. I haven't investigated exactly where the constructor gets called in an iOS page life-cycle, however, if it is in the viewDidLoad, then you have something like 10 seconds for everything to complete, otherwise it will exit automatically. I imagine in your case, this isn't applicable however.
Going forward also try putting your layout controls in the constructor, and move your data task to maybe the OnAppearing override instead.
Using async would definitely be advisable as well, but remember you need to inspect the response from your dataservice, as the error could be embedded within the response also and you will need to detect when it is OK to process the data.
Is there way to handle situation when message is not delivered to server? Dolphin log infors about situation clearly, but I'would like to catch it from code. I was looking for some method like: onError to override like onFinished:
clientDolphin.send(message, new OnFinishedHandlerAdapter() {
#Override
public void onFinished(List<ClientPresentationModel> presentationModels) {
// Do something useful
}
}
});
, but there is nothing like that. Also wrapping send call in try/catch does not work(not suprising since send is not blocking its caller code).
I thing there is definitely some easy way to get informed about undelivered message, but I cant see it.
Thaks, in advace, for answers!
You can assign an onException handler to the ClientConnector - and you are actually supposed to do so. The exception handler will get the exception object passed in that happened in the asynchronous send action.
Below is the default handler that even tells you, what you should do ;-)
Closure onException = { Throwable up ->
def out = new StringWriter()
up.printStackTrace(new PrintWriter(out))
log.severe("onException reached, rethrowing in UI Thread, consider setting ClientConnector.onException\n${out.buffer}")
uiThreadHandler.executeInsideUiThread { throw up } // not sure whether this is a good default
}
I have a BlackBerry App that has a Listener for the Send Button implemented in the CheckIn Screen. Data is sent through a web service. If the data is sent successfully, a confirmation message of "OK" is received. I am trying to switch screens in my BlackBerry App depending on the response received.
FieldChangeListener sendBtnListener = new FieldChangeListener() {
public void fieldChanged(Field field, int context)
{
try {
String alertMsg=sendTextCheckIn();
if(alertMsg.equals("OK"))
{
UiApplication.getUiApplication().invokeLater( new Runnable()
{
public void run ()
{
UiApplication.getUiApplication().pushScreen(new MyScreen());
}
} );
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
However, the above is throwing an App Error 104: IllegalStateException. Can anyone please guide on how to switch screens between a BlackBerry App.
EDIT: I can switch to any other screen but I CAN NOT switch to MyScreen. NOTE: MyScreen is the main (first) screen of the App. The above method sendTextCheckIn() calls another method that is placed inside MyScreen. Has this got anything to do with the error? Please advice.
The 'fieldChanged' event is already running on the UI event thread, so you shouldn't need to do the invokeLater call within it, just call pushScreen directly.
You mention that your problem with IllegalStateException only happens for MyScreen. That makes it sound like something specific with the implementation of MyScreen. Start narrowing down the problem - look at what happens in the constructor of MyScreen, and any events that might get called before the screen is visible. Some of that code is what is causing the problem.
Wrap everything that could possibly raise in exception in try/catch.
Don't do e.printStackTrace() - that won't give you much.
Instead do something like System.err.println ("KABOOM in method abc() - " + e); - seems like more effort, but trust me, that becomes INVALUABLE when debugging issues like this.
Catch Exception, unless you have a VERY good reason to catch a specific a subtype - otherwise you WILL end up with unexpected, and uncaught exceptions, which you will hunt for DAYS.