Monotouch: UIAlertView and WCF services, debugger.StackTrace - wcf

I'm currently using WCF in monotouch to call an existing service and a custom UIAlertView.
The problem is that if I create an UIAlertView as class instance and the I do the following:
public override void ViewDidAppear()
{
_alertView.Message = "Loading...";
_alertView.Show();
_client.GetDataAsync("test");
_client.GetDataCompleted += GetDataCompletedDelegate;
base.ViewDidAppear();
}
void GetDataCompletedDelegate(object sender, GetDataEventArgs)
{
// do someting with data
_alertView.Hide();
}
it works but this advice is written in console : UIAlertView: wait_fences: failed to receive reply: 10004003
else, if I try to run this code:
public override void ViewDidAppear()
{
using(CustomAV _alertView = new CustomAV())
{
_alertView.Message = "Loading...";
_alertView.Show();
_client.GetDataAsync("test");
_client.GetDataCompleted += delegate{
InvokeOnMainThread(delegate{
// do someting with data
_alertView.Hide();
});
};
}
base.ViewDidAppear();
}
the first time the code run, but now alert is shown. The second time the simulator can't startup. Couldn't register "com.yourcompany.wcftest" with the bootstrap server. Error: unknown error code. This generally means that another instance of this process was already running or is hung in the debugger.StackTrace. In this case I have to reboot the machine.
Thank you in advance.
EDIT:
Thank you Geoff, I've checked my code and into GetDataCompletedDelegate I've inserted a function that runs inside the UI Thread.
InvokeOnMainThread(delegate{
doSomething();
});
private void doSomething()
{
// do stuff here
_alertView.Hide();
}
The fency error continues to appear. If I use your solution inside doSomething() method, it works
_alertView.InvokeOnMainThread(delegate{
_alertView.Hide();
});
Why? Maybe I didn't understand, but in the first snippet of code do something() works in the UI thread!! Isn't true?

You have 2 seperate problems here.
1: _alertView.Hide () is not running on the UI thread (this is what causes the fences error)
2: In your second example you're disposing the UIAlertVeiw immediately after creating it, but you have a instance delegate dangled off it. This crashes the runtime in a hard way, and then when you run it again since the old crashed process is still running the simulator wont let you start a second instance.
Use case #1 but do _alterView.InvokeOnMainThread (delegate { _alertView.Hide (); });

Related

Is it better to use the Bus Start method or a class constructor to instantiate objects used by a service

I'm using nServiceBus 5 and have created a number of host endpoints, two of which listen for database changes. (The specifics of how to do this can be found here). The intention is to have a service running in the background which publishes an event message using the Bus when notified to do so by the database listener.
The code which creates the database listener object and handles events is in the Start method, implemented as part of IWantToRunWhenBusStartsAndStops.
So - Is putting the code here likely to cause problems later on, for example if an exception is thrown (yes, I do have try/catch blocks, but I removed them from the sample code for clarity)? What happens when the Start method finishes executing?
Would I be better off with a constructor on my RequestNewQuoteSender class to instantiate the database listener as a class property and not use the Start method at all?
namespace MySample.QuoteRequest
{
public partial class RequestNewQuoteSender : IWantToRunWhenBusStartsAndStops
{
public void Start()
{
var changeListener = new DatabaseChangeListener(_ConnectionString);
// Assign the code within the braces to the DBListener's onChange event
changeListener.OnChange += () =>
{
// code to handle database change event
changeListener.Start(_SQLStatement);
};
// Now everything has been set up.... start it running.
changeListener.Start(_SQLStatement);
}
public void Stop() { LogInfo("Service Bus has stopped"); }
}
}
Your code seems fine to me.
Just a few small things:
Make changeListener a class field, so that it won't be GC (not 100% sure if it would be but just to make sure);
Unsubscribe from OnChange on the Stop() method;
You may also want to have a "lock" around changeListener.Start(_SQLStatement); and the Stop so that there are no racing conditions (I leave that one up to you to figure out if you need it or not);
Does this make sense ?

Marshalling Error by callback

When my callback is called I get:
Marshalling Error has occurred.
What is "Marshalling" ?? and why my callback is invalid. please tell me.
here is the codes.
public Page1()//constructor
{
this.InitializeComponent();
NetworkInformation.NetworkStatusChanged += new Windows.Networking.Connectivity.NetworkStatusChangedEventHandler(OnNetworkStatusChanged);//regist callback
}
void OnNetworkStatusChanged(object arg)//callback method
{
App.mainFrame.Navigate(typeof(Page2));
}
The error message is telling you that the 'Navigate' method is being executed on the wrong thread (and needs to be marshalled, so that it is called on the right thread).
In Windows8, code that interacts with the UI should be executed only on the UI thread - and call-back methods (such as your OnNetworkStatusChanged method above) do not necessarily get called on the UI thread. To ensure that code is executed on the UI thread, and not some other thread, use an idiom like:
// somewhere in your code behind, in code that definitely runs on the UI thread
// - e.g. in the OnLoaded method of your main window:
CoreDispatcher Dispatcher = Windows.UI.CoreWindow.GetForCurrentThread().Dispatcher;
// In your call-back method:
if ((Dispatcher != null) && (!Dispatcher.HasThreadAccess))
{
Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
(obj, invokedArgs) => { App.mainFrame.Navigate(typeof(Page2));},
this,
null
);
}
else
App.mainFrame.Navigate(typeof(Page2));

Metro c++ async programming and UI updating. My technique?

The problem: I'm crashing when I want to render my incoming data which was retrieved asynchronously.
The app starts and displays some dialog boxes using XAML. Once the user fills in their data and clicks the login button, the XAML class has in instance of a worker class that does the HTTP stuff for me (asynchronously using IXMLHTTPRequest2). When the app has successfully logged in to the web server, my .then() block fires and I make a callback to my main xaml class to do some rendering of the assets.
I am always getting crashes in the delegate though (the main XAML class), which leads me to believe that I cannot use this approach (pure virtual class and callbacks) to update my UI. I think I am inadvertently trying to do something illegal from an incorrect thread which is a byproduct of the async calls.
Is there a better or different way that I should be notifying the main XAML class that it is time for it to update it's UI? I am coming from an iOS world where I could use NotificationCenter.
Now, I saw that Microsoft has it's own Delegate type of thing here: http://msdn.microsoft.com/en-us/library/windows/apps/hh755798.aspx
Do you think that if I used this approach instead of my own callbacks that it would no longer crash?
Let me know if you need more clarification or what not.
Here is the jist of the code:
public interface class ISmileServiceEvents
{
public: // required methods
virtual void UpdateUI(bool isValid) abstract;
};
// In main XAML.cpp which inherits from an ISmileServiceEvents
void buttonClick(...){
_myUser->LoginAndGetAssets(txtEmail->Text, txtPass->Password);
}
void UpdateUI(String^ data) // implements ISmileServiceEvents
{
// This is where I would render my assets if I could.
// Cannot legally do much here. Always crashes.
// Follow the rest of the code to get here.
}
// In MyUser.cpp
void LoginAndGetAssets(String^ email, String^ password){
Uri^ uri = ref new URI(MY_SERVER + "login.json");
String^ inJSON = "some json input data here"; // serialized email and password with other data
// make the HTTP request to login, then notify XAML that it has data to render.
_myService->HTTPPostAsync(uri, json).then([](String^ outputJson){
String^ assets = MyParser::Parse(outputJSON);
// The Login has returned and we have our json output data
if(_delegate)
{
_delegate->UpdateUI(assets);
}
});
}
// In MyService.cpp
task<String^> MyService::HTTPPostAsync(Uri^ uri, String^ json)
{
return _httpRequest.PostAsync(uri,
json->Data(),
_cancellationTokenSource.get_token()).then([this](task<std::wstring> response)
{
try
{
if(_httpRequest.GetStatusCode() != 200) SM_LOG_WARNING("Status code=", _httpRequest.GetStatusCode());
String^ j = ref new String(response.get().c_str());
return j;
}
catch (Exception^ ex) .......;
return ref new String(L"");
}, task_continuation_context::use_current());
}
Edit: BTW, the error I get when I go to update the UI is:
"An invalid parameter was passed to a function that considers invalid parameters fatal."
In this case I am just trying to execute in my callback is
txtBox->Text = data;
It appears you are updating the UI thread from the wrong context. You can use task_continuation_context::use_arbitrary() to allow you to update the UI. See the "Controlling the Execution Thread" example in this document (the discussion of marshaling is at the bottom).
So, it turns out that when you have a continuation, if you don't specify a context after the lambda function, that it defaults to use_arbitrary(). This is in contradiction to what I learned in an MS video.
However by adding use_currrent() to all of the .then blocks that have anything to do with the GUI, my error goes away and everything is able to render properly.
My GUI calls a service which generates some tasks and then calls to an HTTP class that does asynchronous stuff too. Way back in the HTTP classes I use use_arbitrary() so that it can run on secondary threads. This works fine. Just be sure to use use_current() on anything that has to do with the GUI.
Now that you have my answer, if you look at the original code you will see that it already contains use_current(). This is true, but I left out a wrapping function for simplicity of the example. That is where I needed to add use_current().

WCF Service method synchronous/async

I have a problem with calling WCF Service methods with Silverlight 3.
private bool usr_OK = false;
clientService.CheckUserMailAsync(this.mailTF.Text);
if (usr_OK == true)
{ isValidationOK = true; }
else { isValidationOK = false; MessageBox.Show("User already exists.", "User registered succes!", MessageBoxButton.OK); }
CheckUserMail should change usr_OK parameter. However it runs in other thread and it does not change the usr_OK param before IF block begins. I've tried thread.join byt the application freezed and i do not know what to do else. Please help me...how can i wait for WCF method to return param usr_OK.
The most direct answer to your question: Don't block on WCF calls. They make it hard for a reason. There, quite likely, is no way to block if you even tried... but don't.
Elaboration: The mode of operation for Silverlight is Asyncronicity. This is something you have to get used to when you are developing in Silverlight. They make it really hard for you to block on anything.
This is a good thing, in my opinion. When you block on the result of something like a WCF service call, you are ultimately blocking the user thread. It does require some getting used to on the developer's part, but again... get used to it.
Lets say you have code that you want to go like this (Synchronous) :
var theResult = clientService.DoSomething(foo);
Process(theResult);
The way to re-write it would be like this (Asynchronous) :
clientService.DoSomethingCompleted += (sender, args) => Process(args.Result);
clientService.DoSomethingAsync(foo);
Taking it a step further, I like to abstract my services out as interfaces (so I can replace them when testing, or running in stand-alone mode while developing). I take that as an opportunity to create an interface that looks like this:
public interface IMyService
{
void DoSomething(string input, Action<string> whenComplete);
}
I implement the service like the async code above, and then when I call it, it is very clean and simple:
myService.DoSomething(foo, Process);
You will find that much of your system will morph into an asynchronous code base, but it might require you to re-adjust your expectations.
Bind the code that checks the usr_OK variable in the event handler for CheckUserMailCompletedEvent
clientService.CheckUserMailCompleted += new EventHandler<CheckUserMailCompletedEventArgs> (clientService_CheckUserMailCompleted);
clientService.CheckUserMailAsync(this.mailTF.Text);
void clientService_CheckUserMailCompleted(object sender, CheckUserMailCompletedEventArgs e) {
if (usr_OK == true) {
isValidationOK = true;
}
else {
isValidationOK = false;
MessageBox.Show("User already exists.", "User registered success!", MessageBoxButton.OK);
}
}

Async Web Service call from Silverlight 3

I have a question regarding the sequencing of events in the scenario where you are calling a wcf service from silverlight 3 and updating the ui on a seperate thread. Basically, I would like to know whether what I am doing is correct... Sample is as follows. This is my first post on here, so bear with me, because i am not sure how to post actual code. Sample is as follows :
//<summary>
public static void Load(string userId)
{
//Build the request.
GetUserNameRequest request =
new GetUserNameRequest { UserId = userId };
//Open the connection.
instance.serviceClient = ServiceController.UserService;
//Make the request.
instance.serviceClient.GetUserNameCompleted
+= UserService_GetUserNameCompleted;
instance.serviceClient.GetGetUserNameAsync(request);
return instance.VM;
}
/// <summary>
private static void UserService_GetUserNameCompleted(object sender, GetUserNameCompletedEventArgs e)
{
try
{
Controller.UIDispatcher.BeginInvoke(() =>
{
//Load the response.
if (e.Result != null && e.Result.Success)
{
LoadResponse(e.Result);
}
//Completed loading data.
});
}
finally
{
instance.serviceClient.GetUserNameCompleted
-= UserService_GetUserNameCompleted;
ServiceHelper.CloseService(instance.serviceClient);
}
}
So my question basically is, inside of my UI thread when I am loading the response if that throws an exception, will the "finally" block catch that ? If not, should i put another try/catch inside of the lambda where I am loading the response ?
Also, since I am executing the load on the ui thread, is it possible that the finally will execute before the UI thread is done updating ? And could as a result call the Servicehelper.CloseService() before the load has been done ?
I ask because I am having intermittent problems using this approach.
The finally block should get executed before the processing of the response inside the BeginInvoke. BeginInvoke means that the code will get executed in the next UI cycle.
Typically the best approach to this type of thing is to pull all the data you need out of the response and store it in a variable and then clean up your service code. Then make a call to BeginInvoke and update the UI using the data in the variable.