Synchronous wrapper for WCF asynchronous calls - c#

We are calling WCF services asyncronously.
public partial class ServiceClient : System.ServiceModel.ClientBase<MyService>, MyService
{
......
}
ServiceClient _serviceclient;
void Getproducts(string filter, string augument, EventHandler<GetCompletedEventArgs> callback)
{
_serviceclient.GetAsyncGetproducts(filter, argument, callback);
}
I want to the Getproducts function to be synchronous. What is the best way to achieve this like the following
void Getproducts(string filter, string augument, EventHandler<GetCompletedEventArgs> callback)
{
_serviceclient.GetAsyncGetproducts(filter, argument, callback);
//wait until callback comes back and return
}
EDIT: The proxy is providing any synchronous calls

You cannot make synchronous networking requests in Silverlight from the UI thread. There's no going around that. Even if you try to trick the asynchronous methods into behaving synchronously, it will not work. That's because if that were possible, the UI thread would be blocked, and the application would appear to be frozen. This happens because the responses to networking requests in SL are always delivered to the UI thread; if you wait for it on the UI thread itself, then you create a deadlock.
You essentially have two options: the preferred one is to actually go the asynchronous route. It's hard at first, if you're only used to synchronous programming, but it's a very valuable skill to have. The other option is to make the call on a background thread. I've tried it and it works, and some people have blogged about it, so you can try it as well. But AFAIK it's not officially supported.

Rather than just passing the callback parameter as the callback you'll want to assign your own callback that executes that method in addition to doing something else. You effectively just need to trigger an event of some sort. I have demonstrated one way using tasks, but you could just as easily use an auto reset event or one of any number of other synchronization methods.
void Getproducts(string filter, string augument, EventHandler<GetCompletedEventArgs> callback)
{
var tcs = new TaskCompletionSource<bool>();
_serviceclient.GetAsyncGetproducts(filter, argument, args =>
{
callback(args);
tcs.SetResult(true);
});
tcs.Task.Wait();
}

Related

Create a Listener to Stop a Method Until Custom Callback Completes

I would like to stop a method until a custom delegate provides a callback from one method to a listener in another in Xamarin.Android, but I am having a lot of trouble understanding the implementation of such a listener.
I have only tried to understand how this could be done, but I'm stuck on how the delegate would be constructed and called.
Let's say that I want this MainActivity method to stop
public async override void OnWindowFocusChanged(bool hasFocus)
{
base.OnWindowFocusChanged(hasFocus);
//how can I create a listener to stop this method until callback from OnPause?
//await a delegate task?
}
and await another method inside a Fragment:
public override void OnResume()
{
base.OnResume();
//I'd like to implement a delegate here to notify the OnWindowFocusChanged that OnResume method has been invoked
//what would be the construction of such?
}
How could I do that?
From my research, I believe I would need to create a delegate task, and then await it's return in OnWindowFocusChanged. However, I am confused about the implementation of such a solution. If anyone could provide even a very basic pseudo-code example, it would help me out a lot.
EDIT: I changed OnPause to OnResume because that's more useful for understanding what I'm trying to do. The below answer references OnPause, but those two are extremely similar methods anyway.
Here is an example that almost does what I'm trying to do; except instead of starting my method when OnResume is invoked, OnWindowFocusChanged stops for 10000ms. So basically, I'd like to replace the timer with a custom delegate (similar to an event) task that returns when Fragment.OnResume is invoked.
public async override void OnWindowFocusChanged(bool hasFocus)
{
base.OnWindowFocusChanged(hasFocus);
//we won't pass this line for 10000ms; how to replace with Task return?
await WaitHere();
}
async Task WaitHere()
{
System.Threading.Thread.Sleep(10000);
}
You could try Task.Run method like:
await Task.Run(() => OnPause());
This would basically create a new thread or use the one you are on and schedule everything after this line as a continuation. So yes, the method would kinda stop, but unless you are on some GUI thread (not to block) or you run some IO task this is unnecessary.
I do not really understand what you are trying to achieve, but you might try to create new OnPauseAsync method that would return Task to get some result from the method when it finishes. This way you would get sequential like mechanism that doesn't block.
If you want to run those methods truly in parallel, but stop execution of OnWindowFocusChanged unitl something hapens in OnPause you should use bare Threads and some synchronization primitives like Mutex or Barrier. Then you would be able to make "main" thread wait until something happens (but it would block! beware). About those fellas you can read more here : LINK_WITH_FOCUS_ON_BARRIER
I am not really sure I got your intentions right, but I hope it helps somehow in the end.
To review:
if you just want to wait for the completion of OnPause and it does only CPU heavy things and you are not on UI thread - do not do anything as there is no profit in using threads etc.
if onPause does some IO heavy things you can use:
Tasks - potentially executed on one thread and doesn't block, control is returned to OnWindowFocusChanged AFTER onPause finishes completely.
Threads - if you want to run some parallel (two threads guaranteed) computations and wait for onPause to signal AT SOME POINT of execution to its caller that it might proceed, you can use e.g Barrier - but beware as this is the most complex solution from programmers perspective and it blocks if you are on UI thread.

WPF/WCF Async Service Call and SynchronizationContext

I have a feeling there's got to be a better solution than what I've come up with; here's the problem:
A WPF form will call a WCF method, which returns a bool. The call itself should not be on the UI thread, and the result of the call will need to be displayed on the form, so the return should be marshaled back on to the UI thread.
In this example I created a "ServiceGateway" class, to which the form will pass a method to be executed upon completion of a Login operation. The gateway should invoke this Login-complete delegate using the UI SynchronizationContext, which is passed upon instantiation of the gateway from the form. The Login method invokes a call to _proxy.Login using an anon. async delegate, and then provides a callback which invokes the delegate ('callback' param) provided to the gateway (from the form) using the UI SynchronizationContext:
[CallbackBehavior(UseSynchronizationContext = false)]
public class ChatServiceGateway : MessagingServiceCallback
{
private MessagingServiceClient _proxy;
private SynchronizationContext _uiSyncContext;
public ChatServiceGateway(SynchronizationContext UISyncContext)
{
_proxy = new MessagingServiceClient(new InstanceContext(this));
_proxy.Open();
_uiSyncContext = UISyncContext;
}
public void Login(String UserName, Action<bool> callback)
{
new Func<bool>(() => _proxy.Login(UserName)).BeginInvoke(delegate(IAsyncResult result)
{
bool LoginResult = ((Func<bool>)((AsyncResult)result).AsyncDelegate).EndInvoke(result);
_uiSyncContext.Send(new SendOrPostCallback(obj => callback(LoginResult)), null);
}, null);
}
The Login method is called from the form in response to a button click event.
This works fine, but I have a suspicion I'm going about the Login method the wrong way; especially because I'll have to do the same for any other method call to the WCF service, and its ugly.
I would like to keep the async behavior and ui synchronization encapsulated in the gateway. Would it be better to have the asynchronous behavior implemented on the WCF side? Basically I'm interested if I can implement the above code more generically for other methods, or if there's a better way all together.
Provided that you're targeting at least VS 2012 and .NET 4.5, async/await is the way to go. Note the lack of SynchronizationContext reference - it's captured under the covers before the await, and posted back to once the async operation has completed.
public async Task Login(string userName, Action<bool> callback)
{
// The delegate passed to `Task.Run` is executed on a ThreadPool thread.
bool loginResult = await Task.Run(() => _proxy.Login(userName));
// OR
// await _proxy.LoginAsync(UserName);
// if you have an async WCF contract.
// The callback is executed on the thread which called Login.
callback(loginResult);
}
Task.Run is primarily used to push CPU-bound work to the thread pool, so the example above does abuse it somewhat, but if you don't want to rewrite the contract implemented by MessagingServiceClient to use asynchronous Task-based methods, it is still a pretty good way to go.
Or the .NET 4.0 way (no async/await support):
public Task Login(string userName, Action<bool> callback)
{
// The delegate passed to `Task.Factory.StartNew`
// is executed on a ThreadPool thread.
var task = Task.Factory.StartNew(() => _proxy.Login(userName));
// The callback is executed on the thread which called Login.
var continuation = task.ContinueWith(
t => callback(t.Result),
TaskScheduler.FromCurrentSynchronizationContext()
);
return continuation;
}
This is a bit of a departure from the way you're currently doing things in that it is the responsibility of the caller to ensure that Login is getting called on the UI thread if they want the callback to be executed on it. That is, however, standard practice when it comes to async, and while you could keep a reference to the UI SynchronizationContext or TaskScheduler as part of your ChatServiceGateway to force the callback/continuation to execute on the right thread, it will blow out your implementation and personally (and this is just my opinion) I would say that that's a bit of a code smell.

If using a Timer control do you need to use Async Task?

I have a Windows form GUI that polls a database server every X minutes. If it finds data it posts the data to an HTTP API. Since I am using a Timer to accomplish the polling do I still need to make use of asynchronous code such as this when calling the API?
Task.Run(async () =>
{
// Call HTTP code here
}).Wait();
I would like the GUI to remain responsive and not lock up.
I am new to asynchronous development in .NET and still not sure how to implement it properly.
Since I am using a Timer to accomplish the polling do I still need to make use of asynchronous code such as this when calling the API?
If you're using System.Threading.Timer or System.Timers.Timer then you dont have to use an async api to keep your GUI responsive as these will invoke the delegate passed to them on a ThreadPool thread. Specifically in your example, you're mistakenly using Wait which waits synchronously on the new thread you're creating, which makes no sense.
If the only thing your delegate is doing is IO bound calls, such as a HTTP request or an async database call (for example, EF exposes async endpoints) then you dont need the extra thread to keep you UI responsive.
Here's an example using Task.Delay (which internally uses a timer) which is purely async:
public async Task PoolAndWaitAsync(int timeToWait)
{
var httpClient = new HttpClient();
while (true)
{
// Query database
var data = await MyDatabase.QueryAsync(..);
if (data != null)
{
var response = await httpClient.PostAsync(..);
}
await Task.Delay(timeToWait);
}
}
It depends on whether you make your HTTP Code asynchronous. Provided you use an async API within that event handler, it should be fine to not wrap in a separate Task.Run.
The Task object iteself performs in async operations. Servy is right. You have to remove the .Wait().
But as long as you want to populate some controls within your async method, you have to be sure to be thread safe.
Cheers, Martin

Turn asynchronous calls into synchronous

Is there any good practice (pattern) in turning asynchronous calls into synchronous?
I have a third party library who's methods are all asynchronos, to get result of almoust any method you must listen to an event, which will bring some context with it.
basically it looks like:
service.BeginSomething(...);
service.OnBeginSomethingCompleted += ;
what I need is to execute some code after BeginSomething when it is really complete (thus after OnBeginSomethingCompleted is triggered). It is very inconvinient to handle the response in the event.
The only way I could think of is running a Thread.Sleep loop and wait till some field on the form is updated, but it doesn't look like very elegant sollution.
I'm using .net 4.0.
You could subclass the main class and provide a synchronous version of the operation. If subclassing is not an option you could create an extension method. Here is how things might look.
public class Subclass : BaseClass
{
public void Something()
{
using (var complete = new ManualResetEventSlim(false))
{
EventHandler handler = (sender, args) => { complete.Set(); };
base.OnBeginSomethingCompleted += handler;
try
{
base.BeginSomething();
complete.Wait();
}
finally
{
base.OnBeginSomethingCompleted -= handler;
}
}
}
}
Update:
One thing I should have pointed out is that this could be problematic in some cases. Consider this example.
var x = new Subclass();
x.BeginSomething();
x.Something();
It should be obvious that the handler in Something could receive the OnBeginSomethingCompleted event from the previous call to BeginSomething. Make sure you guard against this somehow.
Use a ManualResetEvent. In your sync wrapper create it, then pass it to the service.BeginSomething() call as part of the state object. Immediately after the call, WaitOne() on it, this will block.
In the service.OnBeginSomethingCompleted event extract it from the state object and set it, this will unblock the sync caller.
As other said, if possible you should try to make your own code async. If that won't work, does your third-party library support the standard BeginXXX, EndXXX async pattern? If so, then using the TPL would make things easy for you. Your code will look something like this:
using System.Threading.Tasks;
...
var task = Task<TResult>.Factory.FromAsync(
service.BeginSomething, service.EndSomething, arg1, arg2, ..., null);
task.Wait();
var result = task.Result;
The specific overload you'll want to use will depend on how many parameters you need to pass. You can see the list here.
If BeginSomething() returns an IAsyncResult (like a delegate's .BeginInvoke would do), you can get the WaitHandle from that:
service.OnBeginSomethingCompleted += ;
var asyncResult = service.BeginSomething();
asyncResult.AsyncWaitHandle.WaitOne(); // Blocks until process is complete
By the way, by assigning the event handler after starting the async process, you are introducing a race condition where the async call may complete before the event is registered, causing it to never fire.
You might want to look at Reactive Extensions
With Rx you can wrap that into an 'event' basically - the do something like someClass.SomeEvent.Subscribe(d=>...) to subscribe using usually some lambda expression to handle what you need. Also use ObserveOn to handle it on the GUI thread (see the details, this is just a hint).
Other option is to use async await (which is now available for use with VS 2010).
hope this helps
NOTE: Rx have a native support for async methods and turning them into Rx events with pretty much just one call. Take a look at Observable.FromAsyncPattern FromAsyncPattern
The general trend of modern software development (on Windows platform too) is to run, what is possible asynchroniously.
Actually from Windows8 software design guidelines, if the code runs more then 50ms, it has to be asynchronious.
So I would not suggest to block the thread, but instead benefit from that library and provide to the user with some nice looking animation saying "wait, responce comming", or something like this, or some progress bar.
In short, do not block thread, notify a user about what is going on in app and leave it async.
This solution is similar to Brian Gideon's, but I think a little bit cleaner for what you're trying to do. It uses the Monitor object to cause the calling thread to wait until the Completed event is triggered.
public class SomeClass : BaseClass
{
public void ExecuteSomethingAndWaitTillDone()
{
// Set up the handler to signal when we're done
service.OnBeginSomethingCompleted += OnCompleted;
// Invoke the asynchronous method.
service.BeginSomething(...);
// Now wait until the event occurs
lock (_synchRoot)
{
// This waits until Monitor.Pulse is called
Monitor.Wait(_synchRoot);
}
}
// This handler is called when BeginSomething completes
private void OnCompleted(object source, ...)
{
// Signal to the original thread that it can continue
lock (_synchRoot)
{
// This lets execution continue on the original thread
Monitor.Pulse(_synchRoot);
}
}
private readonly Object _synchRoot = new Object();
}

Proper way of delaying the loading of view until a web request or other long running task completes

When doing a webrequest, or any other long running task, I should do it in a separate thread (let's call this thread B) so as not to block the UI. But what's the standard way to take action on the results once the task completes?
I've come up with these options so far:
1) Set up a custom event that fires in thread B when the request completes and that the main thread listen for and handles properly.
2) When the request completes make a InvokeOnMainThread call from thread B.
3) Pass along a reference to the ViewController when starting thread B. And then when the web request completes take whatever action is needed on the viewcontroller in thread B itself.
I use the ThreadPool to carry out these requests. This has the advantage that the runtime automatically adds and removes threads based on their usage and you do not have to manage their life cycle:
class MyViewController : UIViewController {
void PlusOne (string url, string username)
{
ThreadPool.QueueUserWorkItem (delegate {
var wc = new WebClient ();
wc.UploadString (url, "+1");
BeginInvokeOnMainThread (delegate { PlusOneDone (username); });
void PlusOneDone (string username)
{
Console.WriteLine ("Plus one completed for {0}", username);
}
}
In this scenario, I use a couple of anonymous methods, by using nested anonymous methods (or lambdas), you can easily propagate the parameters (in this case "username") from the original thread that calls PlusOne" to the callback m
Another alternative is to use the System.Net.WebClient class which provides an higher level API (than WebRequest and WebResponse) and are easier to use properly (e.g. to minimize memory allocations, deal with different encoding...) and also provides several easy=to-use Async methods.
E.g. WebClient.DownloadStringAsync method and WebClient.OnDownloadStringCompleted event.
I usually call a method which runs on a seperate thread with a callback action.
void StartRequest(Uri url, Action<T> callback) {
using (var ns = new NSAutoReleasePool ()){
// Do some work
callback(T);
}
}
With the callback(T) having access to whatever you want to manipulate.
You can also look at the documentation on threading TweetStation or MonoTouch.Dialog for examples of ASync callbacks.
Of course you can use delegates to the same end, or events etc... You are on the right track!

Categories

Resources