2014-10-11 120 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.在某個層次中執行異步只會影響該層次。