Silverlight - Waiting for asynchronous call to finish before returning from a method - multithreading

I have a Silverlight application that uses WCF services and also uses the Wintellect Power Threading library to ensure logic executes fully before the application continues. This is achieved by calling back to the application using delegates so it can continue after the service call has completely finished.
I wish to achieve the same thing in another part of my application but without the use of callbacks e.g. call method that uses WCF service to say load an object from the database, wait for this to return and then return the Id of the object from the original method called.
The only way I could see to do this was to carry out the call to the WCF service in a helper library which loads the object on a different thread and the original method would keep checking the helper library (using static variables) to wait for it to complete and then return it.
Is this the best way to achieve this functionality? If so here are details of my implementation which is not working correctly.
public class MyHelper
{
private static Thread _thread;
private static User _loadedObject;
public static GetUser()
{
return _loadedObject;
}
public static void LoadObject(int userId)
{
_loadedObject = null;
ParameterizedThreadStart ts = new ParameterizedThreadStart(DoWork);
_thread = new Thread(ts);
_thread.Start(userId);
}
private static void DoWork(object parameter)
{
var ae = new AsyncEnumerator();
ae.BeginExecute(DoWorkWorker(ae, Convert.ToInt32(parameter)), ae.EndExecute);
}
private static IEnumerator<Int32> DoWorkWorker(AsyncEnumerator ae, int userId)
{
// Create a service using a helper method
var service = ServiceHelper.GetService<IUserServiceAsync>();
service.BeginGetUserById(userId, ae.End(), null);
yield return 1;
_loadedObject = service.EndGetUserById(ae.DequeueAsyncResult());
_thread.Abort();
}
}
My method then is:
public int GetUser(int userId)
{
MyHelper.LoadObject(userId);
User user = MyHelper.GetUser();
while (user == null)
{
Thread.Sleep(1000);
user = MyHelper.GetUser();
}
return user.Id;
}
The call to the get the user is executed on a different thread in the helper method but never returns. Perhaps this is due to the yield and the calling method sleeping. I have checked the call to get the user is on a different thread so I think everything should be kept separate,

The whole construct you are using does not match current best practices of Silverlight. In Silverlight your data access methods (via WebServices of course) are executed asynchronously. You should not design around that, but adapt your design accordingly.
However calling services sequentially (which is different than synchonously) can be valid in some scenarios. In this blog post I have shown how to achieve this by subscribing the Completed event of the remote call and block the UI in the meantime, with which the workflow looks and feels like normal async calls.

I believe calls to the server from Silverlight apps use events that fire on the UI thread; I think that's part of the Silverlight host environment in the browser and can't be worked around. So trying to call back to the server from another thread is never going to end well. If you are waiting in program code in the UI thread, your never going to get the call result events from your WCF calls.
You can simulate a synchronous call from a non-UI thread with a callback on the UI thread, but that is probably not what you want. It's better to bite the bullet and make your program logic work with the async calls Silverlight gives you.

If you code against the Interface created for your service reference you can call the Begin and End methods 'synchronously' for each one of your service calls, we then pass in an Action<T> to execute after the End methods has completed. Take note that you have to do this from a dispatcher. This is very close to making a synchronous call as the code to run after the call is still written where the call is made, and it executes after the service call is completed. It does however involve creating wrapper methods but we also worked around that by hiding our wrappers and generating them automatically. Seems like a lot of work but isn't, and ends up being more elegant than all the event handlers etc. Let me know if you need more info on this pattern

Related

Monotouch PerformSelector on specific thread with multiple arguments and callbacks

I've been having some issues with threading in monotouch. My app makes use of an external library which I've linked with and it works fine. Because of the nature of the app and the library I have to make all the calls to it on a single separate thread.These calls will generally be :
Random non deterministic caused by user
Every t miliseconds(around 20ms). Like an update function
After reading for a bit I decided to try out NSThread. I've managed to call the Update function by attaching an NSTimer to the thread's RunLoop and it's all working fine. The problem that I'm having now is calling other methods on the same thread. I read somewhere that using PerformSelector on the RunLoop adds the selector invocation to the RunLoop's queue and invokes it when available, which is basically exactly what I need. However the methods that I need to call :
Can have multiple paramteres
Have callbacks, which I need to invoke on the main thread, again with multiple parameters
For the multiple parameters problem I saw that NSInvocation can be a solution, but the life of me I can't figure out how to do it with monotouch and haven't found any relevant examples.
For the actuals calls that I need to make to the library, I tried doing a generic way in which I can call any function I choose via delegates on a particular thread, which sort of works until I'm hit with the multiple parameters and/or callbacks to the main thread again with multiple parameters. Should I maybe just register separate selectors for each (wrapped)function that I need to call from the library?
I'm not hellbent on using this approach, if there is a better way I'm open to it, it's just that after searching for other options I saw that they don't fit my case:
GCD(not even sure I have it in monotouch) spawns threads on it's own whenever necessary. I need a single specific thread to schedule my work on
NSInvocationQueue(which uses GCD internally from what I read) does the same thing.
pThreads, seem overkill and managing them will be a pain(not even sure I can use them in monotouch)
I'm not an iOS developer, the app works fine with monodroid where I had Runnables and Handlers which make life easier :) . Maybe I'm not looking at this the right way and there is a simple solution to this. Any input would be appreciated.
Thanks
UPDATE
I was thinking of doing something along these lines :
Have a simple wrapper :
class SelectorHandler : NSObject
{
public static Selector Selector = new Selector("apply");
private Action execute;
public SelectorHandler(Action ex)
{
this.execute = ex;
}
[Register("apply")]
private void Execute()
{
execute();
}
}
Extend NSThread
public class Daemon : NSThread
{
public void Schedule(Action action)
{
SelectorHandler handler = new SelectorHandler(action);
handler.PerformSelector(SelectorHandler.Selector, this, null, true);
}
}
Then, when I want to call something I can do it like this :
private Daemon daemon;
public void Call_Library_With_Callback(float param, Action<int> callback)
{
daemon.Schedule(() =>
{
int callbackResult = 0;
//Native library calls
//{
// Assign callback result
//}
daemon.InvokeOnMainThread(() =>
{
callback(callbackResult);
});
});
}

Response from service as a callback is not concurrent in actionscript?

I am developing an AIR application for iOS/ Android and I am using a backend service for database operations. The backend service provides asynchronous API's for loading and saving the data. I happen to stumble at a piece of logic which caught my attention:
Main
public funciton loadPlayerData():void
{
service.loadData();
// Busy lock
while( !service.client == true );
// Do some stuff after the client is received
}
Service
public function loadData()
{
// Call the external service and specify success callback as
// onSuccess
}
public function onSuccess():void
{
this.client = true;
}
public var client:Boolean = false;
What I am trying to do in the above code is that I am calling an async operation on service and while it is fetching data from server, I am busy spinning waiting for the client to set true in the callback. According to my understanding, this is how locking is done for resources in operating system and all. ( Though there are more elegant solutions in operating system other than busy wait ).
But the results are such that the Main gets stuck in an infinite busy waiting implying that onSuccess never gets called. The reason, according to my understanding is that until and unless the the current execution ends ( or when the stack of current execution is completely popped out), control is not given to the callback Function and hence my implementation results in never ending spin wheel. My basic assumption that thread is multiplexed from time point of view is flawed and thats the explanation I can deduce from the premise.
I want to know whats the actual reason behind the above scenario? How far I am correct in my deduction and what are the details behind execution of actionscript code in scenario like these ?
The AS3 runtime is not multithreaded - your script runs on a single thread with certain operations internally running on a separate thread (like network calls, etc.) The only way to properly handle your situation is to split up your work into multiple steps; you then initiate the first step (calling the remote service) and pass a callback function. There's no need to wait in a loop (in fact, it hurts you as you discovered) - when the network call is done, your callback will be called and you can initiate the next step of your processing. Until this 2nd step is called, the rest of your program should assume that the data from the remote service is not available.
Your code would be something like:
public funciton loadPlayerData():void
{
service.loadData();
// Nothing else here - you must wait for the data
// to be avaiable.
}
public function loadData()
{
// Call the external service and specify success callback as
// onSuccess
}
public function onSuccess():void
{
// Call logic that performs "Do some stuff
// after the client is received" from your
// question.
}
I think this should solve the issue, depending on how you determine that onSuccess is called (I assume its a function for an Event Listener.)
First off, your Service class needs to inherit EventDispatcher, either directly or indirectly, so that you gain access to dispatchEvent(event) function.
Main
public funciton loadPlayerData():void
{
service.loadData();
service.addEventListener(Event.COMPLETE, onServiceLoadedData);
}
private function onServiceLoadedData(e:Event):void{
...
}
Service
...
public function onSuccess():void
{
//after everything has been loaded
dispatchEvent(new Event(Event.COMPLETE));
}
As a side note, if you need to access stuff from your Service class and you don't want to handle it through setter/getter variables and such like, you can make a custom Event and pass all the necessary Information there.

SignalR Wait for result

Trying to push a message into UI and receive some result to return in synchronous way from web-service.
Method code goes as follows.
[OperationContract]
public string DecypherCaptcha(string captcha)
{
var connection = new HubConnection("http://localhost:51806");
IHubProxy hub = connection.CreateHubProxy("robo");
string decaptcha = null;
hub.On("captchaDecyphered", decyphered =>
{
decaptcha = decyphered;
});
connection.Start().Wait();
hub.Invoke<string>("DecypherCaptcha", new object[] { captcha });
return decaptcha;
}
The issue is that method finishes before value is obtained from hub's captchaDecyphered. However the expression { decaptcha = decyphered; } triggers fine from server after method exits.
Adding ManualResetEvent flag and WaitOne() for it doesn't solve the problem freezing the execution and preventing hub.On("captchaDecyphered" from firing.
Any ideas how to synchronize this?
UPDATE#1 Small notice. Cannot avoid using the intermediate synchronous WCF web-service acting as SignalR client, because of pretty specific robots sitting behind, which are able to interact with outer world only by calling webservices synchronously. Basically in this scenario when robot faces captcha it calls the web-service passing it via SignalR to UI for manual recognition.
UPDATE#2 Thanks to #Ken's inspiring advice got it working by enclosing the connection establishing and hub method invocation into separate 'Thread' followed by waiting with 'ManualResetEvent':
new Thread(() =>
{
connection.Start().Wait();
hub.Invoke<string>("DecypherCaptcha", new object[] { captcha });
}).Start();
sync.WaitOne();
Have previously been trying to start from 'Task' supposing it would run on separate thread implicitly, but with no luck.
You could have the DecypherCaptcha hub method on the SignalR server return the deciphered captcha as a Task<string> instead on invoking captchaDecyphered.
You may want to use a TaskCompletionSource to help you create the appropriate task. Basically you could call tcs.SetResult(deciphered) and return tcs.Task instead of calling Clients.Caller.captchaDecyphered(deciphered).
Then your client-side code code would simply be:
[OperationContract]
public string DecypherCaptcha(string captcha)
{
var connection = new HubConnection("http://localhost:51806");
IHubProxy hub = connection.CreateHubProxy("robo");
connection.Start().Wait();
return hub.Invoke<string>("DecypherCaptcha", captcha).Result;
}
You've got several options.
(1) Spin off the request to the SignalR hub onto a separate thread, probably using the static ThreadPool class, and then add in all the ManualResetEvent stuff. That way it won't block when you're waiting on the SignalR method to return.
(2) Make the DecypherCaptcha method asynchronous. It looks to me like the DecypherCaptcha() is intended to be a WCF method that in turn wraps a SignalR method. If that's the case, forgetting for a moment whether this is a wise approach, you could still call a WCF method on the client when the captchaDecyphered SignalR method completes. But if it's not intended to be a WCF method, then you could have DecypherCaptcha() either (a) return a Task<T>, and only flag the Task to be complete when the captchaDecyphered completes; or (b) pass in a Func<T> as a continuation parameter, and call that when the captchaDecyphered completes.
In general, one of the things that makes asynchronous programming difficult is that except for the very top-level method, you generally need to make every method that calls an asynchronous method itself asynchronous, all the way up and down the stack, either through the Async pattern (nasty), or continuation passing (better) or through a Task object + async/await (probably best). So adding in a single asynchronous method often results in significant changes to your application, all the way through. That's one of the many reasons why the new async and await keywords in .NET 4.5 are so helpful, because they help to encapsulate the necessary changes when you start making your application asynchronous.
You can use the generic Invoke method where you can specify the type of result you expect. With the method you CAN use .Result to wait for the result.
string result = IHubProxy.Invoke<string>("GetString").Result;

Handling threading and web requests on Windows Phone 7

How can you make a background web request and then update the UI, but have all the code that does the web requesting/parsing in a separate class so you can use it in multiple places? I thought I could use the classes methods as event handlers for a BackgroundWorker class, like
APIHelper mHelper = new APIHelper("http://example.com?foo=bar");
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork +=new DoWorkEventHandler(mHelper.GetResponse);
bw.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(mHelper.HandleResponse);
bw.RunWorkerAsync();
where APIHelper has the method
public void GetResponse(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker) sender;
WebRequest request = HttpWebRequest.Create(this.URL);
IAsyncResult result = (IAsyncResult)
request.BeginGetResponse(ResponseCallback, request);
}
but then I don't know how to access the worker thread from ResponseCallback and, anyway, HandleResponse gets called first (obviously). (I tried putting in result.AsyncWaitHandle.WaitOne(); but I get a NotSupportedException error.) Yet I can't work out how to make the web request call synchronously. I'm clearly trying to go about this the wrong way, but I have no idea what the right way is.
ETA:
My aim is to be able to go:
user clicks (a) button(s) (on various pages)
a "working" message is displayed on the UI thread (and then input is blocked)
in a background thread my APIHelper class makes the relevant API call, gets the response, and passes it back to the UI thread; I only seem to be able to do this by starting another thread and waiting for that to return, because there's no synchronous web requests
the UI thread updates with the returned message (and input continues as before)
I can do the first two bits, and if I have the response, I can do the last bits, but I can't work out how to do the middle bit. Hopefully that made it clearer!
It took me several tried before I found there is a Dispatcher.
During the BackgroundWorker's dowork and complete methods you can call:
this.Dispatcher.BeginInvoke(() =>
{
// UPDATE UI BITS
});
I think the Dispatcher is only available in the view. So I'm not sure if the methods can exist outside of the xaml.cs
Put whatever you want to update in your UI; when updating an ObservableCollection you must do the update of you items in the Dispatcher.BeginInvoke too
This link might be a good read too:
http://www.windowsphonegeek.com/articles/All-about-Splash-Screens-in-WP7-ndash-Creating-animated-Splash-Screen
Update to assist notes
This is just a rough idea mind you...
bw.DoWork +=new DoWorkEventHandler(DoWork);
bw.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(Complete)
// At least I think the EA is DoWork....
public void DoWork(object sender, DoWorkEventArgs e)
{
mHelper.GetResponse();
this.Dispatcher.BeginInvoke(() =>
{
UIObject.Visibility Collapse.
});
// Wait and do work with response.
});
}
public void Complete(object sender, RunWorkerCompleteEventArgs e)
{
this.Dispatcher.BeginInvoke(() =>
{
UIObject.Visible ....
});
}
I'd put all this logic in a viewmodel that the viewmodel of each page inherits from.
Have the pages bind to properties on the viewmodel (such as ShowLoading, etc.) which the model updates appropriately. i.e. before making the webrequest and in the callback.
As you won't be running the viewmodel code in the UI thread you also wouldn't need to run in a separate BackgroundWorker and you'll be able to access the properties of the viewmodel without issue.
It might be useful if you use a helper class that I have developed for WebDownload purposes during WP7 development.
I'm using it in 2-3 WP7 apps and no problem so far. Give it a go to see if it helps. You can get the class from the my blog linked bellow:
http://www.manorey.net/mohblog/?p=17#content
[NOTE] When working with this class you don't need to run anything in a background worker or new thread; it handles it all asynchronously.

Windows Service and multithreading

Im working on a Windows Service in which I would like to have two threads. One thread should look for updates (in a RSS feed) and insert rows into a DB when updates is found.
When updates are found I would like to send notification via another thread, that accesses the DB, gets the messages and the recipients and then sends notifications.
Perhaps the best practice isn't to use two threads. Should I have db-connections in both threads?
Could anyone provide me with tips how to solve this?
The major reason to make an application or service multithreaded is to perform database or other background operations without blocking (i.e. hanging) a presentation element like a Windows form. If your service depends on very rapid polling or expects db inserts to take a very long time, it might make sense to use two threads. But I can't imagine that either would be the case in your scenario.
If you do decide to make your service multithreaded, the two major classes in C# that you want to look into are BackgroundWorker and ThreadPool. If you want to do multiple concurrent db inserts (for example, if you want to execute an insert for each of multiple RSS feeds polled at the same time), you should use a ThreadPool. Otherwise, use a BackgroundWorker.
Typically, you'd have a db access class that would have a method to insert a row. That method would create a background worker, add DoWork handler to some static method in that db access class to the background worker, then call DoWorkAsync. You should only have db connection settings in that one class in order to make maintaining the code easier. For example:
public static class DbAccess
{
public void InsertRow(SomeObject entity)
{
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += InsertRow_DoWork;
bg.RunWorkerCompleted += InsertRow_RunWorkerCompleted;
bg.RunWorkerAsync(entity);
}
private void InsertRow_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bg = sender as BackgroundWorker;
SomeObject entity = e.Argument as SomeObject;
// insert db access here
}
private void InsertRow_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// send notifications
// alternatively, pass the InsertRow method a
// delegate to a method in the calling class that will notify
}
}

Resources