WPF/WCF Async Service Call and SynchronizationContext - c#

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.

Related

Wrap .NET Remoting async method in TPL Task

We have a legacy .NET Remoting-based app. Our client client libary currently supports only synchronous operations. I would like to add asynchronous operations with TPL-based async Task<> methods.
As proof of concept, I have set up a basic remoting server/client solution based a modified version of these instructions.
I have also found this article that describes how to convert APM-based asynchronous operations to TPL-based async tasks (using Task.Factory.FromAsync)
What I'm unsure about is whether I'm compelled to specify the callback function in .BeginInvoke() and also to specify the .EndInvoke(). If both are required, what exactly is the difference between the callback function and .EndInvoke(). If only one is required, which one should I use to return values and also ensure that I have no memory leaks.
Here is my current code where I don't pass a callback to .BeginInvoke():
public class Client : MarshalByRefObject
{
private IServiceClass service;
public delegate double TimeConsumingCallDelegate();
public void Configure()
{
RemotingConfiguration.Configure("client.exe.config", false);
var wellKnownClientTypeEntry = RemotingConfiguration.GetRegisteredWellKnownClientTypes()
.Single(wct => wct.ObjectType.Equals(typeof(IServiceClass)));
this.service = Activator.GetObject(typeof(IServiceClass), wellKnownClientTypeEntry.ObjectUrl) as IServiceClass;
}
public async Task<double> RemoteTimeConsumingRemoteCall()
{
var timeConsumingCallDelegate = new TimeConsumingCallDelegate(service.TimeConsumingRemoteCall);
return await Task.Factory.FromAsync
(
timeConsumingCallDelegate.BeginInvoke(null, null),
timeConsumingCallDelegate.EndInvoke
);
}
public async Task RunAsync()
{
var result = await RemoteTimeConsumingRemoteCall();
Console.WriteLine($"Result of TPL remote call: {result} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
}
}
public class Program
{
public static async Task Main(string[] Args)
{
Client clientApp = new Client();
clientApp.Configure();
await clientApp.RunAsync();
Console.WriteLine("Press any key to continue...");
Console.ReadKey(false);
}
}
The difference between between the callback function and .EndInvoke() is that the callback will get executed on an arbitrary thread from the threadpool. If you must be sure that you obtain result from the read on the same thread as the one you called BeginInvoke, then you should not use the callback, but poll the IAsyncResult object and call .EndInvoke() when the operation is complete.
If you call .EndInvoke() right after .Beginnvoke(), you block the thread until the operation completes. This will work, but will scale poorly.
So, what you do seems all right!
You must specify the callback function for efficiency reasons. If the FromAsync only has an IAsyncResult to work with it cannot be notified when that async result completes. It will have to use an event to wait. This blocks a thread (or, it registers a threadpool wait maybe which is not so bad).
Efficient async IO requires callbacks at some level.
If you are going async I assume you are doing this because you have many concurrent calls or the calls are very long running. For that reason you should use the more efficient mechanism.
If you don't have many or long running calls then async is not going to help you with performance in any way but it might still make GUI programming easier.
So this is not correct:
public async Task<double> RemoteTimeConsumingRemoteCall()
{
var timeConsumingCallDelegate = new TimeConsumingCallDelegate(service.TimeConsumingRemoteCall);
return await Task.Factory.FromAsync
(
timeConsumingCallDelegate.BeginInvoke(null, null),
timeConsumingCallDelegate.EndInvoke
);
}
To make sure that your implementation indeed does not block any thread I'd do this: Insert a Thread.Sleep(100000) on the server side and issue 1000 concurrent calls on the client. You should find that the thread count does not rise.

Where does async and await end? Confusion

I have a program which has no purpose but to help me understand how async and await works. It's a console application which parses XML and waits for a name to be returned, either the surname or the first name. Here is the code:
static void Main(string[] args)
{
Task<string> name = GetFirstParsedName();
name.Wait();
if (name.IsCompleted)
{
Console.WriteLine(name.Result);
}
Console.ReadLine();
}
static async Task<string> GetFirstParsedName()
{
string xmlSnippet = #"<person>
<FirstName>Chamir</FirstName>
<Surname>Bodasing</Surname>
<Gender>Male</Gender>
<Nationality>South African</Nationality></person>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlSnippet);
XmlParser xmlParser = new XmlParser();
Task<string> t_GetFirstName = xmlParser.GetFirstName(xmlDoc);
Task<string> t_GetSurname = xmlParser.GetSurname(xmlDoc);
Task<string> t_firstReturnedName = await Task.WhenAny(new Task<string>[] { t_GetFirstName, t_GetSurname });
string firstReturnedName = await t_firstReturnedName;
return firstReturnedName;
}
static async Task<string> GetFirstName(XmlDocument personXml)
{
string firstName = personXml.SelectSingleNode("//FirstName").InnerText;
await Task.Delay(5000);
return firstName;
}
static async Task<string> GetSurname(XmlDocument personXml)
{
string surname = personXml.SelectSingleNode("//Surname").InnerText;
await Task.Delay(1);
return surname;
}
It seems like it only makes sense to use the async method when you don't have to return a value to a main method. Unless it means setting a global class property which can then be accessed. If not, in order to await the method, all methods need to be async which in turn means that the return type must be Task<T>. It seems like it never ends unless I explicitly have to write the following code (as in above main method):
Task<string> name = GetFirstParsedName();
name.Wait();
if (name.IsCompleted)
{
Console.WriteLine(name.Result);
}
Is my understanding correct at all? I have to use the result property to get the value here and from reading up about this, it seems that this is not the best practice.
It seems like it only makes sense to use the async method when you don't have to return a value to a main method. Unless it means setting a global class property which can then be accessed.
Your async methods can return Task<T> to return a value to its caller. Asynchronous methods do not work very well if they depend on side effects (i.e., setting properties / globals); they work much better if your code is more pure (i.e., taking parameters and returning results).
If not, in order to await the method, all methods need to be async which in turn means that the return type must be "Task" . It seems like it never ends
This is why one of the central principles of async is "async all the way". In most applications, this is exactly what you should do. Eventually, the "async chain" generally ends in an async void event handler (for UI apps) or an async Task<T> entry point (for ASP.NET apps). Console apps are unusual since they do require an explicit Wait()/Result or equivalent in their Main method.
After all, the whole point of async is to free up the calling thread. If the next method up the call stack blocks that same thread until the async code is complete, well, that was a whole lot of work for no benefit...
It seems like it only makes sense to use the async method when you don't have to return a value to a main method.
Why do you say that? It makes sense to use an async method where-ever you have a naturally asynchronous operation ongoing. No matter if that operation has a return value or doesn't.
in order to await the method, all methods need to be async which in turn means that the return type must be "Task" . It seems like it never ends
That's correct. Async spreads in your code like a plage, from the bottom to the top of your stack. It usually reaches the highest calling place in your stack (be it a console Main method or a UI event handler). That's the advantage of using async, it allows you to asynchronously wait an operation while freeing the calling thread. This can help, for example, if you have a WebAPI endpoint which needs to handle a large amount of requests concurrently. If you spend most of your time querying a database, you can free that calling thread in the meanwhile to serve more requests.
Is my understanding correct at all? I have to use the result property to get the value here and from reading up about this, it seems that this is not the best practice.
You have to use the Result property because a console application is a special case, where Main cant be marked as async (unless you're using ASP.NET CoreCLR console app). If this was a UI event handler or an ASP.NET action, you'd properly await the async call.
Well, async keyword let's compiler know that your method is going to execute series of asynchronous calls that should most likely be awaited but should not block the main (or UI) thread.
To help you understand async-await a little bit, here is some simple example:
Consider the scenario, when user clicks 'Save' button on WinForm's app, and some UI operation is started asynchronously in different Thread.
The code is :
private Task SomeUIOperation()
{
// ui operation
return Task.Run(() =>
{
this.Invoke(new Action(() => this.BackColor = Color.Aquamarine));
Thread.Sleep(10000);
this.Invoke(new Action(() => this.BackColor = Color.Gray));
});
}
private async void button1_Click(object sender, EventArgs e)
{
await SomeUIOperation();
// some other stuff
}
If we do not use async-await here UI thread will become unresponsive for 10 seconds.
It's an example of how you usually use async-await, you use it when you want some piece of code to be executed only when asynchronous operation is completed and in the same time you do not want the main thread to be blocked.
And console application is not the best project type for testing and learning Async-Await

How does the async/await return callchain work?

I had a situation recently where I had an ASP.NET WebAPI controller that needed to perform two web requests to another REST service inside its action method. I had written my code to have functionality separated cleanly into separate methods, which looked a little like this example:
public class FooController : ApiController
{
public IHttpActionResult Post(string value)
{
var results = PerformWebRequests();
// Do something else here...
}
private IEnumerable<string> PerformWebRequests()
{
var result1 = PerformWebRequest("service1/api/foo");
var result = PerformWebRequest("service2/api/foo");
return new string[] { result1, result2 };
}
private string PerformWebRequest(string api)
{
using (HttpClient client = new HttpClient())
{
// Call other web API and return value here...
}
}
}
Because I was using HttpClient all web requests had to be async. I've never used async/await before so I started naively adding in the keywords. First I added the async keyword to the PerformWebRequest(string api) method but then the caller complained that the PerformWebRequests() method has to be async too in order to use await. So I made that async but now the caller of that method must be async too, and so on.
What I want to know is how far down the rabbit hole must everything be marked async to just work? Surely there would come a point where something has to run synchronously, in which case how is that handled safely? I've already read that calling Task.Result is a bad idea because it could cause deadlocks.
What I want to know is how far down the rabbit hole must everything be
marked async to just work? Surely there would come a point where
something has to run synchronously
No, there shouldn't be a point where anything runs synchronously, and that is what async is all about. The phrase "async all the way" actually means all the way up the call stack.
When you process a message asynchronously, you're letting your message loop process requests while your truly asynchronous method runs, because when you go deep down the rabit hole, There is no Thread.
For example, when you have an async button click event handler:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await DoWorkAsync();
// Do more stuff here
}
private Task DoWorkAsync()
{
return Task.Delay(2000); // Fake work.
}
When the button is clicked, runs synchronously until hitting the first await. Once hit, the method will yield control back to the caller, which means the button event handler will free the UI thread, which will free the message loop to process more requests in the meanwhile.
The same goes for your use of HttpClient. For example, when you have:
public async Task<IHttpActionResult> Post(string value)
{
var results = await PerformWebRequests();
// Do something else here...
}
private async Task<IEnumerable<string>> PerformWebRequests()
{
var result1 = await PerformWebRequestAsync("service1/api/foo");
var result = await PerformWebRequestAsync("service2/api/foo");
return new string[] { result1, result2 };
}
private async string PerformWebRequestAsync(string api)
{
using (HttpClient client = new HttpClient())
{
await client.GetAsync(api);
}
// More work..
}
See how the async keyword went up all the way to the main method processing the POST request. That way, while the async http request is handled by the network device driver, your thread returns to the ASP.NET ThreadPool and is free to process more requests in the meanwhile.
A Console Application is a special case, since when the Main method terminates, unless you spin a new foreground thread, the app will terminate. There, you have to make sure that if the only call is an async call, you'll have to explicitly use Task.Wait or Task.Result. But in that case the default SynchronizationContext is the ThreadPoolSynchronizationContext, where there isn't a chance to cause a deadlock.
To conclude, async methods shouldn't be processed synchronously at the top of the stack, unless there is an exotic use case (such as a Console App), they should flow asynchronously all the way allowing the thread to be freed when possible.
You need to "async all the way up" to the very top of the call stack, where you reach a message loop that can process all of the asynchronous requests.

Synchronous wrapper for WCF asynchronous calls

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();
}

C# have async function call synchronous function or synchronous function call async function

I'm writing a C# .Net 4.5 library for doing common sql database operations (backup, restore, execute script, etc.). I want to have both synchronous and asynchronous functions for each operation, as this library will be used by both console and GUI apps, but I don't want to duplicate code everywhere. So as I see it, I have two options:
Write the code that does the work in a synchronous function, and then just wrap it in a task for the async function, like so:
public void BackupDB(string server, string db)
{
// Do all of the work and long running operation here
}
public async Task BackupDBAsync(string server, string db)
{
await Task.Factory.StartNew(() => BackupDB(server, db)).ConfigureAwait(false);
}
Write the code that does the work in an asynchronous function, and call it from a synchronous function using .Wait():
public async Task BackupDBAsync(string server, string db)
{
// Do all of the work and long running operation here, asynchronously.
}
public void BackupDB(string server, string db)
{
BackupDBAsync(server, db).Wait(); // Execution will wait here until async function finishes completely.
}
Is one option better than the other? Is one a best practice? Or are there any other (better) alternatives?
I know that one caveat to using .Wait() is that all of the await statements in the async function have to use .ConfigureAwait(false) to avoid deadlocks (as discussed here), but since I'm writing a library that will never need to access the UI or WebContext I am safe to do that.
I'll note too that the SQL library typically also has both synchronous and async functions that can be used, so if doing the work in the sync function, I would call their sync function, and if doing the work in the async function, I would call their async function.
Thoughts/suggestions are appreciated.
-- edit: I've also posted this question on the MSDN forums here to try and get an official MS response --
I want to have both synchronous and asynchronous functions for each operation, as this library will be used by both console and GUI apps, but I don't want to duplicate code everywhere.
The best answer is: don't.
Stephen Toub has two excellent blog posts on this topic:
Should I expose asynchronous wrappers for synchronous methods?
Should I expose synchronous wrappers for asynchronous methods?
He recommends exposing asynchronous methods as asynchronous, and synchronous methods as synchronous. If you need to expose both, then encapsulate common functionality in private (synchronous) methods, and duplicate the async/sync differences.
I had a similar situation where some applications needed the data to be loaded synchronously and others asyc. I decided to created an interface that I called my dataloader:
public interface IIMViewModelDL {
void LoadProjects(AssignProjects callback);
}
The AssignProjects callback is just a simple delegate that takes in the returned list of projects:
public delegate void AssignProjects(IEnumerable<Project> results);
Now, the beauty of this is that you can work with the interface without knowing whether you are dealling in sync or async.
Three classes are created: one base, one sync, and one async:
public abstract class BaseViewModelDL {
protected IEnumerable<Project> LoadProjects() {
BaseServiceClient client = new BaseServiceClient();
return client.Projects();
}
public class SynchronousViewModelDL : BaseViewModelDL, IIMViewModelDL {
public void LoadProjects(AssignProjects callback) {
callback(base.LoadProjects());
}
public class AsyncIMViewModelDL : BaseViewModelDL, IIMViewModelDL {
public void LoadProjects(AssignProjects callback) {
BackgroundWorker loadProjectsAsync = new BackgroundWorker();
loadProjectsAsync.DoWork += new DoWorkEventHandler(LoadProjectsAsync_DoWork);
loadProjectsAsync.RunWorkerCompleted += new RunWorkerCompletedEventHandler(LoadProjectsAsync_RunWorkerCompleted);
loadProjectsAsync.RunWorkerAsync(callback);
}
void LoadProjectsAsync_DoWork(object sender, DoWorkEventArgs e) {
var results = new ObservableCollection<Project>(base.LoadProjects());
e.Result = new object[] { results, e.Argument };
}
void LoadProjectsAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
AssignProjects callback = (AssignProjects)((object[])e.Result)[1];
IEnumerable<Project> results = (IEnumerable<Project>)((object[])e.Result)[0];
callback(results);
}
Now, in your application, you can decide how you want to load data...this could be injected through an IoC container, but is hard coded for demo purposes:
private ViewModelDataLoaders.IIMViewModelDL dataLoader = new ViewModelDataLoaders.AsyncIMViewModelDL();
Now, your calling code looks the same and is none the wiser to whether it is async or sync:
private void LoadProjects() {
dataLoader.LoadProjects(
delegate(IEnumerable<Project> results) {
Projects = new ObservableCollection<Project>(results);
});
}
I use this regularly for unit testing (sync), WPF applications (async), and console applications (sync).
There does not seem to be a point to simply mark a method as async without using an await. Marking it as async does not make it asynchronous, it allows you to use awaits (the code executed in the await is what happens asynchronously, and then the rest of the async method will also be done asynchronously) in the body of the method:
Typically, a method modified by the async keyword contains at least one await expression or statement. The method runs synchronously until it reaches the first await expression, at which point it is suspended until the awaited task is complete. In the meantime, control is returned to the caller of the method. If the method does not contain an await expression or statement, then it executes synchronously. A compiler warning alerts you to any async methods that don't contain await because that situation might indicate an error. For more information, see Compiler Warning CS4014.
From: async

Categories

Resources