2014-10-11 123 views
1

我正在处理一个项目,该项目需要使用特定格式的某些数据创建XML,并将其发送给第三方服务,然后处理结果。这里的第三方功能是验证XML的数据和格式,然后创建一个编码的字符串(“标记”),证明一切符合要求。然后将该邮票添加到原始XML并存储在数据库中。异步方法内同步Web服务调用的缺点

现在,第三方还是要被选中的,所以我必须创建我的项目,以便它可以在发布之前使用两种不同的Web服务(至今),并有机会添加另一个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 
    } 
} 

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

但随后打我... Althought我会打电话包装方法异步,Web服务方法仍将被同步调用。

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

或者这是总体上的问题的错误方法?

请记住,这是C#4.0,因此(可悲)异步等待超出范围。

回答

0

我没有发现你的方法有什么问题,你正在做的好处是你可以连续调用三个服务调用的每一个的Begin Invoke,因为它们不会因为异步调用而被阻塞,并且在内部在每个Web服务调用中,必须等待逻辑/进程完成,然后才能通过CallBack方法发送结果。在Web服务内部,可以进行同步操作,直到除非您可以再次异步执行多个作业。

如果您打算同步调用服务,而不是BeginInvoke,则调用Invoke,然后它会阻塞,直到每个Web服务都按顺序返回,从而减慢整个过程,因为它们不会在单独的线程。

你是对的异步等待是一个更清洁的选择,但你不能在当前版本中使用它。

1

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

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

你似乎认为调用一个异步的web服务,内部是同步的(或其他方式)可能有一个缺点。不是这种情况。 Neither of the two parties can even tell how the other one is implemented.在某个层次中执行异步只会影响该层次。