Reputation: 2164
I'm working on a project that needs to create a XML with certain data on a certain format, send it to a third-party service, and then process the result. The third-party's function here is to validate both the data and the format of the XML, and then create a codified string (a "stamp") certifying everything complies with the requeriments. This stamp has then to be added to the original XML and stored on database.
Now, the third-party is still to be chosen, so I have to create my project in a way it can work with (so far) two different web services before release, with the chance of adding another one and, after release, changing the chosen one. Although the final result is the same (the "stamping" of the XML) each web service does things differently e.g. one returns only the stamp string, while the other returns the XML with the stamp included, and the pending one returns the byte array of a zip file containing the XML (I don't know who told them that was a good idea, but meh, that's another story)
With this in mind, I decided to create a static class that wraps the web service calls (one method per web service). All these methods receive the XML and return either the "stamped" XML or an XML with an error code and message in case something went wrong. The class that handles the data has then only to create the required XML, call one of these methods, and process the result.
So far it looks something like this:
public class EDocument
{
//This class handles all the data that will be included in the XML
public void Stamp()
{
//Here the XML string is created, sent to the correspondig third-party web service, and processed back
string xmlString;
//code to create the XML
//...
//If needed, I only have to change this line to call the corresponding method
WebServiceCalls.MainWebServiceCall stamper = WebServiceCalls.FirstServiceCall;
stamper.BeginInvoke(xmlString, StampCallback, null);
}
public void StampCallback(IAsyncResult ar)
{
AsyncResult result = (AsyncResult)ar;
WebServiceCalls.MainWebServiceCall caller = (WebServiceCalls.MainWebServiceCall)result.AsyncDelegate;
string response = caller.EndInvoke(ar);
//Call another async method to save to database the stamp, create the XML file, e-mail and store it, and notify the results...
//or create the exception with the error details and raise event here to notify the error
}
}
Web service calls...
public static class WebServiceCalls
{
//Here I'll put the necessary web service calls. In the end there will be only one,
//but if on future the web service changes, a method with the same signature will be created here
//replacing the previous one
public delegate string MainWebServiceCall(string XmlData);
public static string FirstServiceCall(string XmlData)
{
FirstWebService firstWs = new FirstWebService();
string serviceResult = firstWs.Stamp(XmlData); //This returns only the stamp string
//Check the result, add the stamp to the original XML or create the error XML, and return...
return serviceResult;
}
public static string SecondServiceCall(string XmlData)
{
SecondWebService secondWs = new SecondWebService();
string serviceResult = secondWs.Stamp(XmlData); //This returns the XML with the stamp already added
//Check the result, create the error XML if something went wrong, and return...
return serviceResult;
}
public static string ThirdServiceCall(string XmlData)
{
ThirdWebService thirdWs = new ThirdWebService();
string serviceResultString;
byte[] serviceResult = thirdWs.Stamp(XmlData); //This (sigh) returns the byte array of a ZIP file...
//Unzip the file, check the result, create the corresponding XML and return...
return serviceResultString;
}
}
But then it hit me... Althought I'll be calling the wrapper methods asynchronously, the web service method will still be called synchronously.
Question is: what are the disadvantages of this? should I instead call the web service asynchronously on every caller method, handle the callback, raise the notifying event, catch it on the Edocument class, process the result and raise it's corresponding event? Wouldn't this be making things over-complicated considering the possible future changes this project could have?
Or is this overall a wrong approach of the problem?
Keep in mind that this is C# 4.0, so (sadly) async-await is out of scope.
Upvotes: 1
Views: 898
Reputation: 171246
You are not using async IO at all. Delegate.BeginInvoke
uses the thread-pool. In server apps this is purely damaging in almost all situations. Async IO is threadless.
Either use synchronous code, or async IO.
You seem to think that calling a webservice asynchronously that internally is synchronous (or the other way around) might have a disadvantage. This is not the case. Neither of the two parties can even tell how the other one is implemented. Going async in a certain tier only affects that tier.
Upvotes: 1