所以我正在研究一個使用Web服務的客戶端。我使用服務中的WSDL和XSD文件生成代理類,並且所有同步函數都可以正常工作。但是,考慮到它們的同步性質,進行任何呼叫都會導致UI在呼叫結束之前停止響應。使用異步方法的經典原因,對嗎?在C#4.0 Web服務客戶端中需要幫助實現異步調用
問題是,我還在讀學位,對於異步編程知之甚少。我試圖在網上讀到它(我的僱主甚至有一本書全天候訂閱),但我很難理解我應該如何進行呼叫以及如何處理響應。下面是我有:
/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://localhost:8080/getRecords", RequestNamespace="http://www.<redacted>.com/ws/schemas", ResponseNamespace="http://www.<redacted>.com/ws/schemas", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlArrayAttribute("records", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
[return: System.Xml.Serialization.XmlArrayItemAttribute("list", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public record[] getRecords([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string username, [System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] [System.Xml.Serialization.XmlArrayItemAttribute("list", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="integer", IsNullable=false)] string[] ids) {
object[] results = this.Invoke("getRecords", new object[] {
username,
ids});
return ((record[])(results[0]));
}
/// <remarks/>
public void getRecordsAsync(string username, string[] ids) {
this.getRecordsAsync(username, ids, null);
}
/// <remarks/>
public void getRecordsAsync(string username, string[] ids, object userState) {
if ((this.getRecordsOperationCompleted == null)) {
this.getRecordsOperationCompleted = new System.Threading.SendOrPostCallback(this.OngetRecordsOperationCompleted);
}
this.InvokeAsync("getRecords", new object[] {
username,
ids}, this.getRecordsOperationCompleted, userState);
}
private void OngetRecordsOperationCompleted(object arg) {
if ((this.getRecordsCompleted != null)) {
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.getRecordsCompleted(this, new getRecordsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
}
}
還有這個:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class getRecordsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
private object[] results;
internal getRecordsCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
base(exception, cancelled, userState) {
this.results = results;
}
/// <remarks/>
public record[] Result {
get {
this.RaiseExceptionIfNecessary();
return ((record[])(this.results[0]));
}
}
}
這:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]
public delegate void getRecordsCompletedEventHandler(object sender, getRecordsCompletedEventArgs e);
我選擇了這個例子,因爲同步調用有返回類型和異步不 - 至少不要在函數調用本身。我知道getRecordsCompletedEventArgs類具有正確的返回類型,這就是我將如何從調用中獲取數據的方式。我似乎無法弄清楚的是如何真正做到這一點。
比方說,我代替我的當前呼叫getRecords與getRecordsAsync:
如何建立客戶端異步調用完成時如何應對?我需要使用已寫入的LINQ過程將XML放入文件中,我需要記錄操作的成功或失敗,並且需要通知用戶操作已完成。
我該如何確保使呼叫實際發生異步?我記得在某個時候讀到,只是調用一個異步SOAP方法實際上並不是針對當前線程異步發生的,除非您先做其他事情。有小費嗎?
我還有什麼其他的主要考慮因素嗎?(如:「如果你忘記這樣做,它會炸掉你的程序!」)
這些都是我一直沒能找到令人信服的答案,公司到目前爲止的所有問題。提前感謝您提供任何幫助。
我不是100%在這個,但你想嘗試在Web服務內異步調用的東西?如果Web服務需要很長時間才能完成,那麼應該是異步的代碼應該是客戶端代碼,而不是服務代碼。這個想法是,如果你在服務中產生一個新的線程,現有的線程將退出並返回SOAP響應,並且你的客戶端將永遠不會收到發生在服務端的事件處理程序的通知。 – Richthofen