Asynchronous web method without timeout

I need a console application that will call webmethod.

It should be asynchronous and without a timeout (we do not know how long this method takes to solve the problem.

This is a good way:

[WebMethod] [SoapDocumentMethod(OneWay = true)] 

??

+4
source share
2 answers

Do not use one-way if you need results.

First, if you need an answer from your method, you do not want [SoapDocumentMethod(OneWay = true)] . This attribute creates a call "fire and oblivion", which never returns a response to the boat and must return void . Instead, use a regular method call and name it async.

One or two methods?

If you use ASMX, there are two main solutions: one method with a very long timeout or two methods (like @Aaronaught suggested above ): one to start the operation and return the operation identifier, and the other to transmit the identifier and get the results (if available).

Personally, I would not recommend this two-component approach in most cases because of the additional complexity, including:

  • Client and server code must be changed to support two-step calling
  • ASP.NET internal objects such as Request and Response not available when called from a background task launched using ThreadPool.QueueUserWorkItem .
  • throttling on a busy server becomes much more difficult if multiple threads are involved with each request.
  • the server should hang on the results until the client picks them up (or you decide to throw them away), which can eat RAM if the results are large.
  • you cannot pass large, intermediate results back to the client

However, in some scenarios, the approach using two methods can scale better and be more resistant to broken network connections between the client and server. If you need to pick up the results a few hours later, this should be considered. But your operations take only a few minutes, and you can guarantee that the client will remain connected, given the complexity of the adjuvant function of the 2-method, I would consider that this is the last tool that will be used only if the solution with one method does not match your needs.

In any case, the solution requires two parts. First, you need to call the method asynchronously from the client. Secondly, you need to lengthen timeouts on both the client and server. I use both below.

Call ASMX Web Services Asynchronously

To invoke an ASMX web service asynchronously from a command-line application, see this article starting on page 2. This shows how to invoke a web service asynchronously from a .NET cilent application using the new Asynchronous Event-Based Template . Note that the older .NET 1.0 approach described here , which relies on the BeginXXX / EndXXX proxy methods, is no longer recommended anymore since Visual Studio Proxy Generator does not create these methods. It is better to use an event-based template as described above.

Here is an excerpt / adaptation from the article above, so you can get an idea of ​​the code involved:

 void KickOffAsyncWebServiceCall(object sender, EventArgs e) { HelloService service = new HelloService(); //Hookup async event handler service.HelloWorldCompleted += new HelloWorldCompletedEventHandler(this.HelloWorldCompleted); service.HelloWorldAsync(); } void HelloWorldCompleted(object sender, HelloWorldCompletedEventArgs args) { //Display the return value Console.WriteLine (args.Result); } 

Increase server and client latency

To prevent timeouts, http://www.dotnetmonster.com/Uwe/Forum.aspx/asp-net-web-services/5202/Web-Method-TimeOut provides a good summary of how to configure both client and server timeouts. You did not indicate in your question if you have a server method or only a client call, so the excerpt below covers both cases:

There are two sets of settings that will affect the wait time of a call to the webservice behavior:

** ASP.NET server httpruntime server timeout on the web server, this is configured through the following element:

httpRuntime Element (ASP.NET Settings Diagram)
http://msdn2.microsoft.com/en-us/library/e1f13641.aspx

<configuration> <system.web>
<httpRuntime .............
ExecutionTimeout = "45"
............... / "> </system.web> </ configuration>

Also, make sure you set <compile debug = "false" / "> so that the timeout works correctly.

** If you are using wsdl.exe or VS IDE, add the web link generated by the proxy to call the webservice methods, there is also a timeout for the client proxy class (obtained from the SoapHttpClientProtocol class). This is the Timeout property obtained from the WebClientProtocol class:

WebClientProtocol.Timeout Properties http://msdn2.microsoft.com/en-us/library/system.web.services.protocols.webclientprotocol.timeout.aspx

Therefore, you might consider customizing these two values ​​to suit your application scenario. Here the former thread also mentioned this:

http://groups.google.com/group/microsoft.public.dotnet.framework.webservices/browse_thread/thread/73548848d0544bc9/bbf6737586ca3901

Please note that I highly recommend making your timeouts long enough to cover your longest operation (plus enough buffer to be safe if things are slower), but I would not recommend disabling timeouts at all. This is usually a bad programming practice, allowing unlimited waiting times, as an erroneous client or server can permanently disable another. Instead, just do timeouts for a very long time - and make sure you register instances where your clients or servers time out, so you can detect and diagnose the problem when this happens!

Finally, to repeat the comments above: for new code, it is best to use WCF. But if you are stuck using ASMX web services, this solution should work.

+5
source

If the method is actually one-way, and you do not need the result or ever need to monitor the status of your request, then this is good enough.

If you need a result (in the end) or you need to check the status of an operation, this will not work very well. What your method should do in this case is to start work in the background thread and then immediately return the identifier, which you can use in another web method to search for the state.

So something like this:

 public enum JobStatus { Running, Completed, Failed }; public class MyService : WebService { [WebMethod] public int BeginJob() { int id = GetJobID(); // Save to a database or persistent data source SaveJobStatus(id, JobStatus.Running); ThreadPool.QueueUserWorkItem(s => { // Do the work here SaveJobStatus(id, JobStatus.Completed); } return id; } [WebMethod] public JobStatus GetJobStatus(int id) { // Load the status from database or other persistent data source return ( ... ) } } 

This method starts up and another way to check its status. This allows the client to periodically conduct a survey. This is not a good system, but you do not have many options with ASMX.

Of course, if you need an answer from this operation, it is much better to use WCF. WCF provides callback contracts that you can use to start a one-way operation and subscribe to a notification when this operation is completed, which eliminates the need for the survey above.

So, we summarize all this:

  • If you don't need any answers or status updates, just use IsOneWay = true .

  • If you need updates and you can use WCF on the service side, use this with a callback contract. In any case, you should use WCF for new web service projects.

  • If you need updates and cannot use WCF, do the work in the background thread and implement a periodic polling system with an additional web method for checking the status.

+3
source

Source: https://habr.com/ru/post/1304253/


All Articles