如何在Web服务中使用异步任务概念来为每个请求提供服务。 [英] How to use async task concept in web service to serve each request.
问题描述
我在C#中创建了一个Web服务,它使用2个参数创建一个XML字符串,并将HTTP请求发送到一个服务器,并使用从服务器收到的响应进行回复。现在我的问题是,我如何使用异步任务来处理对我的Web服务的多个请求,以便我的所有请求者都得到响应。以下是我的httprequest代码。
I have created one web service in C# which takes 2 parameters make one XML string and send the HTTP Request to one server and reply with the response received from Server. Now my question is, how i can use Async task to handle multiple requests to my web service so all my requester get the response. following is my code for httprequest.
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string postXMLData(String Session, String Token)
{
string destinationUrl = "https://data.getdata.com";
String requestXml= "<ENVELOPE> <HEADER> <VERSION>1</VERSION> <REQVERSION>1</REQVERSION> <TALLYREQUEST>EXPORT</TALLYREQUEST> <TYPE>DATA</TYPE> <ID>TPGETCOMPANIES</ID><SESSIONID>" + Session + "</SESSIONID> <TOKEN>" + Token + "</TOKEN> </HEADER><BODY> <DESC> <STATICVARIABLES><SVINCLUDE>CONNECTED</SVINCLUDE></STATICVARIABLES></DESC></BODY> </ENVELOPE>";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(destinationUrl);
byte[] bytes;
bytes = System.Text.Encoding.ASCII.GetBytes(requestXml);
request.ContentType = "text/xml; encoding='utf-8'";
request.ContentLength = bytes.Length;
request.Method = "POST";
request.Headers.Add("ID","TPGETCOMPANIES");
request.Headers.Add("SOURCE","EA");
request.Headers.Add("TARGET","TNS");
//request.Headers.Add("CONTENT-TYPE","text/xml;charset=utf-8");
request.Headers.Add("Accept-Encoding","identity");
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
string responseStr = new StreamReader(responseStream).ReadToEnd().Trim();
return responseStr;
//responseStr.ToString();
}
else
{
return "Problem in getting resp";
}
return null;
}
}
我尝试过:
我试图托管这个简单的服务,但它无法同时提供多个请求。
What I have tried:
I have tried to host this simple service but it is not able to serve multiple request at the same time.
推荐答案
WebService
类早于任务并行库,并且对async
任务一无所知。 />
但是, 支持较旧的IAsyncResult
/ APM模式:
如何:创建异步Web服务方法 [ ^ ]
并且可以使用任务
来实现该模式:
使用任务实现APM模式 [ ^ ]
使用任务实现APM模式使用.NET进行并行编程 [ ^ ]
从Stephen Toub的博客文章中的ToApm
扩展方法开始:
TheWebService
class pre-dates the Task Parallel Library, and knows nothing aboutasync
tasks.
However, it does support the olderIAsyncResult
/ APM pattern:
How to: Create Asynchronous Web Service Methods[^]
And it's possible to implement that pattern using aTask
:
Implementing the APM Pattern By Using Tasks[^]
Using Tasks to implement the APM Pattern | Parallel Programming with .NET[^]
Start with theToApm
extension method from Stephen Toub's blog post:
public static class TaskExtensions
{
// Found at: http://blogs.msdn.com/b/pfxteam/archive/2011/06/27/10179452.aspx
public static Task<TResult> ToApm<TResult>(this Task<TResult> task, AsyncCallback callback, object state)
{
if (task == null) throw new ArgumentNullException(nameof(task));
if (task.AsyncState == state)
{
if (callback != null)
{
task.ContinueWith(t => callback(t), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
}
return task;
}
var tcs = new TaskCompletionSource<TResult>(state);
task.ContinueWith(delegate
{
if (task.IsFaulted) tcs.TrySetException(task.Exception.InnerExceptions);
else if (task.IsCanceled) tcs.TrySetCanceled();
else tcs.TrySetResult(task.Result);
if (callback != null) callback(tcs.Task);
}, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
return tcs.Task;
}
}
然后,将您的实现移动到私有 async
方法返回任务< string>
,并使用扩展方法使其适应APM模式:
Then, move your implementation to a private async
method returning a Task<string>
, and use the extension method to adapt it to the APM pattern:
public class Service1 : System.Web.Services.WebService
{
private async Task<string> PostXMLDataAsync(string session, string token)
{
...
}
[WebMethod]
public IAsyncResult BeginPostXMLDataAsync(string session, string token, AsyncCallback callback, object asyncState)
{
return PostXMLDataAsync(session, token).ToApm(callback, asyncState);
}
[WebMethod]
public string EndPostXMLDataAsync(IAsyncResult asyncResult)
{
// Using ".GetAwaiter().GetResult()" prevents exceptions from being wrapped in an AggregateException:
return ((Task<string>)asyncResult).GetAwaiter().GetResult();
}
}
对于实现,您可能希望查看使用 System.Net.Http命名空间 [ ^ ],因为它提供了更好的异步 - 知道API比原始 HttpWebRequest
/ HttpWebResponse
类。
但是,如果你这样做,你应该确保为所有请求使用一个静态 HttpClient
实例,如下所述:您正在使用HttpClient错误,这会破坏您的软件稳定性ASP.NET Monsters [ ^ ]
For the implementation, you might want to look at using the classes from the System.Net.Http namespace[^], as that provides a nicer async-aware API than the raw HttpWebRequest
/ HttpWebResponse
classes.
However, if you do that, you should make sure you use a single static HttpClient
instance for all requests, as described here: You're using HttpClient wrong and it is destabilizing your software | ASP.NET Monsters[^]
private static readonly HttpClient Http = new HttpClient();
private async Task<string> PostXMLDataAsync(string session, string token)
{
const string destinationUrl = "https://data.getdata.com";
string requestXml= "<ENVELOPE> <HEADER> <VERSION>1</VERSION> <REQVERSION>1</REQVERSION> <TALLYREQUEST>EXPORT</TALLYREQUEST> <TYPE>DATA</TYPE> <ID>TPGETCOMPANIES</ID><SESSIONID>" + Session + "</SESSIONID> <TOKEN>" + Token + "</TOKEN> </HEADER><BODY> <DESC> <STATICVARIABLES><SVINCLUDE>CONNECTED</SVINCLUDE></STATICVARIABLES></DESC></BODY> </ENVELOPE>";
var requestMessage = new HttpRequestMessage(HttpMethod.Post, destinationUrl);
requestMessage.Content = new StringContent(requestXml, System.Text.Encoding.UTF8, System.Net.Mime.MediaTypeNames.Text.Xml);
requestMessage.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("identity"));
requestMessage.Headers.Add("ID", "TPGETCOMPANIES");
requestMessage.Headers.Add("SOURCE", "EA");
requestMessage.Headers.Add("TARGET", "TNS");
var response = await Http.SendAsync(requestMessage).ConfigureAwait(false);
// Check the status code:
if (!response.IsSuccessStatusCode) return "Problem in getting resp";
// Or, to throw an exception:
// response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
这篇关于如何在Web服务中使用异步任务概念来为每个请求提供服务。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!