- Generate asynchronous operations
This one gives you the exact same result as choosing to generate async operations in VS2010 i.e. for each service method you will have 2 additional client methods: *Async & *Completed. One of my previous posts partially explains how to use them and provide more links on that topic. - Generate task-based operations
When writing your async code this option allows you to take advantage of the Task Parallel Library (TPL) that was introduced with .Net 4. This post is not meant to be a TPL tutorial, but there are many sites explaining the concept. My personal favourite is "Introduction to Async and Parallel Programming in .NET 4" by Dr. Joe Hummel. For now it is enough to say that using tasks (i.e. TPL library) can make handling your async scenarios easier and the async code more readable/maintainable.
The interesting thing is that since .Net 4.5 and its async/await feature you can easily benefit from using task-based async operation even in fully synchronous scenarios. You may start wondering what can be advantages of using async techniques & libraries in fully synchronous scenarios. The answer is: performance! If you are using regular synchronous methods, they block current thread until it receives the response. In case of task-based operations combined with async/await feature the thread is released to the pool while waiting for the service response.
Obviously this advantage only applies in some scenarios e.g. in web applications running on IIS, where requests are handled in parallel by threads from the pool. If you are working a single threaded client app you will not benefit from this approach.
Sample code
In this post I'll re-use the sample code from my last post. I'll convert synchronous calls to my sample web service so they use task-based async operations. So, let me remind you the interface of the web service that we will use:
[ServiceContract] public interface IStringService { [OperationContract] string ReverseString(string input); }Now, let's update the service client. There is actually not much conversion that needs to be done. First, you need to ensure that the generated code includes task-based async operations (right click on service reference -> "Configure service reference"). Once you have async operations generated, you need to transform the existing code to work with tasks and use async/await feature:
public async Task<string> ReverseAsync(string input) { return await _client.ReverseStringAsync(input); }Comparing to the original, purely synchronous method we have following changes:
- Async keyword added to the method signature
- Method return type changed to Task<string> (i.e. original return type 'wrapped' with Task)
- Different service client method used: ReverseStringAsync instead of ReverseString
- Await keyword added before the client method call
- "*Async" suffix added to the method name (recommended convention)
Updated integration test:
[TestMethod] public void TestStringHelper_Reverse() { StringHelper sh = new StringHelper(); string result = sh.ReverseAsync("abc").Result; Assert.AreEqual("cba", result); }Notice that I only added a call to .Result property as this time the method returns Task.
And the unit test:
[TestMethod] public void TestStringHelper_Reverse() { // Create channel mock Mock<IStringServiceChannel> channelMock = new Mock<IStringServiceChannel>(MockBehavior.Strict); // setup the mock to expect the ReverseStringAsync method channelMock.Setup(c => c.ReverseStringAsync("abc")).Returns(Task.FromResult("cba")); // create string helper and invoke the ReverseAsync method StringHelper sh = new StringHelper(channelMock.Object); string result = sh.ReverseAsync("abc").Result; Assert.AreEqual("cba", result); //verify that the method was called on the mock channelMock.Verify(c => c.ReverseStringAsync("abc"), Times.Once()); }The main thing to notice here is that we use Task.FromResult to create a task wrapping our sample result when mocking the client method.
Asp.Net MVC
I already mentioned that described approach will only be beneficial in some types of apps e.g. webapps running on IIS. A sample Asp.Net MVC4 controller action using our async client could look as follows:public async Task<ActionResult> Index() { ViewBag.Message = "Reversed 'abc' string: " + await _stringHelper.ReverseAsync("abc"); return View(); }Again, notice async and await keywords added to the action method, supported in MVC4.
A detailed tutorial for using aync/await with MVC4 can be found here.
Sample code for this post on my github:
https://github.com/filipczaja/BlogSamples/tree/master/MockingWCFClientWithMoqAsync
No comments:
Post a Comment