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

时间:2014-10-11 17:18:43

标签: c# .net asynchronous

我正在开发一个项目,需要使用特定格式的某些数据创建XML,将其发送到第三方服务,然后处理结果。这里的第三方功能是验证XML的数据和格式,然后创建一个证明一切符合requeriments的编码字符串(“戳”)。然后将此戳记添加到原始XML并存储在数据库中。

现在,仍然需要选择第三方,因此我必须以一种可以在发布前使用(到目前为止)两种不同的Web服务的方式创建我的项目,并有可能添加另一个,之后释放,改变所选择的。虽然最终结果是相同的(XML的“标记”),但每个Web服务的处理方式不同,例如:一个只返回戳记字符串,而另一个返回包含戳记的XML,而挂起的一个返回包含XML的zip文件的字节数组(我不知道谁告诉他们这是一个好主意,但是meh ,那是另一个故事)

考虑到这一点,我决定创建一个包装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
    }
}

网络服务电话......

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,所以(遗憾的是)async-await超出了范围。

1 个答案:

答案 0 :(得分:1)

您根本没有使用异步IO。 Delegate.BeginInvoke使用线程池。在服务器应用程序中,这几乎在所有情况下都是纯粹的破坏性。 Async IO is threadless.

使用同步代码或异步IO。

您似乎认为异步调用Web服务在内部是同步的(或者相反),可能会有缺点。不是这种情况。 Neither of the two parties can even tell how the other one is implemented.某个层中的异步只会影响该层。