所以我正在研究一个使用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