异步方法内部的同步web服务调用的缺点



我正在处理一个项目,该项目需要创建一个具有特定格式的特定数据的XML,将其发送给第三方服务,然后处理结果。第三方在这里的功能是验证XML的数据和格式,然后创建一个编码的字符串("stamp")来证明所有内容都符合要求。然后必须将此戳添加到原始XML中并存储在数据库中。

现在,第三方仍有待选择,所以我必须在发布前创建我的项目,使其能够(到目前为止)使用两个不同的web服务,并有机会添加另一个,发布后更改所选的。虽然最终的结果是相同的(XML的"盖章"),但每个web服务做的事情都不同,例如,一个只返回stamp字符串,而另一个返回包含stamp的XML,而挂起的一个则返回包含XML的zip文件的字节数组(我不知道是谁告诉他们这是个好主意,但我,那是另一回事)

考虑到这一点,我决定创建一个静态类来封装web服务调用(每个web服务一个方法)。所有这些方法都接收XML,并返回"盖章"的XML或带有错误代码和消息的XML,以防出现问题。然后,处理数据的类只需要创建所需的XML,调用其中一个方法,并处理结果。

到目前为止,它看起来像这样:

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服务调用。。。

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;
    }
}

但我突然想到…尽管我将异步调用包装器方法,但web服务方法仍将同步调用。

问题是:这样做的缺点是什么?我是否应该在每个调用方方法上异步调用web服务,处理回调,引发通知事件,在Edocument类上捕获它,处理结果并引发相应的事件?考虑到这个项目未来可能发生的变化,这不会让事情变得过于复杂吗?

或者这是一个错误的问题处理方法?

请记住,这是C#4.0,所以(遗憾的是)异步等待超出了范围。

您根本没有使用异步IO。Delegate.BeginInvoke使用线程池。在服务器应用程序中,这在几乎所有情况下都是完全有害的。异步IO是无线程的。

要么使用同步代码,要么使用异步IO。

您似乎认为异步调用内部同步(或相反)的Web服务可能有缺点。事实并非如此。双方甚至都不知道另一方是如何实施的。在某一层中异步只会影响该层。

最新更新