Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an async webservice method

I've tried to read up on async methods and am now trying to create my own async method. The method is a webservice call that returns a list of error logs. I'm not sure that I've understood correctly so I thought I'd share my code to see if I should do anything different.

All I want the code to do is return a list of errorlogs by calling a method GetAllErrorLogs(), that is a synchronized method. Since it can take a second to fetch all the error logs I want to have the opportunity to do other stuff once I called the GetAllErrorLogs() method. Here is the code.

[WebMethod]
public async Task<List<ErrorLog>> GetAllErrorLogs()
{
    List<ErrorLog> errorLogs = new List<ErrorLog>();

    await System.Threading.Tasks.Task.Run(() => {
        errorLogs = ErrorLogRepository.GetAllErrorLogs();
    });


    if (errorLogs == null)
        return new List<ErrorLog>();

    return errorLogs;
}

Thanks!

like image 774
Andreas Avatar asked Aug 21 '13 20:08

Andreas


People also ask

Can Web services be asynchronous?

The asynchronous web services receives the request, sends a confirmation message to the initiating client, and starts process the request. Once processing of the request is complete, the asynchronous web service acts as a client to send the response back to the callback service.

How do you call a webservice method asynchronously in C#?

First, you tell the Web service to begin execution by calling the Begin method. The second step, calling the End method, completes the web service call and returns the response. To call a web service asynchronously, a client thread can use a WaitHandle.

Should Web API methods be async?

In the context of Web API, Asynchronous programming is used to improve the scalability of the application. By applying asynchronous programming using async and await there won't be any direct performance gain in speed instead application will be able to handle more concurrent requests.


3 Answers

I recently gave a talk at ThatConference on async on the server side, and I address this issue in the slides.

On the server side, you want to avoid the use of Task.Run and other constructs that queue work to the thread pool. As much as possible, keep thread pool threads available for handling requests.

So, ideally your repository would have an asynchronous method GetAllErrorLogsAsync, which would itself be asynchronous. If GetAllErrorLogs cannot be asynchronous, then you may as well just call it directly (removing the await Task.Run).

Since it can take a second to fetch all the error logs I want to have the opportunity to do other stuff once I called the GetAllErrorLogs() method.

If you have a GetAllErrorLogsAsync available, then this can easily be done using Task.WhenAll. However, if GetAllErrorLogs is synchronous, then you can only do this by doing parallel work in your request (e.g., multiple calls to Task.Run followed by Task.WhenAll).

Parallel code on the server must be approached with great trepidation. It is only acceptable in a very limited set of scenarios. The entire point of async on the server side is to use fewer threads per request, and when you start parallelizing, you're doing the opposite: multiple threads per request. This is only appropriate if you know your user base is very small; otherwise, you'll kill your server scalability.

like image 182
Stephen Cleary Avatar answered Oct 19 '22 22:10

Stephen Cleary


I found this great codeproject detailed article about how to achieve that

http://www.codeproject.com/Articles/600926/Asynchronous-web-services-call-in-ASP-NET

like image 34
Mauricio Gracia Gutierrez Avatar answered Oct 19 '22 23:10

Mauricio Gracia Gutierrez


**This is potentially wrong, read comments or spinoff question at HttpContext.Current after an await

If ErrorLogRepository.GetAllErrorLogs() is not thread-safe, it will cause weird bugs and potentially exception out. Make sure your code is ready for multi-threaded operation before switching to async methods, this is obviously very trivial advice but often overlooked. For example, if you reference HttpContext.Current in your methods, your code will die in the async method, and sometimes even AFTER the await. The reason is that the code within the async block will potentially be run on a separate thread, which will not have access to the same HttpContext.Current thread-static property, and await gets compiled into two methods. All code before an await gets run on one thread, and then calls the code after an await keyword as a continuation, but potentially on yet another thread. So sometimes your code will even work in an async block, only to choke unexpectedly after it gets "out" of the async back to what you think is a synchronous part of your code (but in reality everything after an await keyword is already not guaranteed to be the original thread).

like image 40
welegan Avatar answered Oct 19 '22 22:10

welegan