gpt4 book ai didi

c# - 需要帮助在 C# 4.0 Web 服务客户端中实现异步调用

转载 作者:行者123 更新时间:2023-12-05 02:24:01 30 4
gpt4 key购买 nike

所以我正在开发一个使用网络服务的客户端。我使用服务中的 WSDL 和 XSD 文件来生成代理类,所有同步功能都运行良好。但是,考虑到它们的同步性质,进行任何调用都会导致 UI 停止响应,直到调用完成。使用异步方法的经典理由,对吧?

问题是,我还在学校攻读学位,对异步编程知之甚少。我试着在线阅读它(我的雇主甚至订阅了 24x7 书籍),但我很难掌握我应该如何调用电话以及如何处理响应。这是我拥有的:

    /// <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:

  1. 如何设置客户端在异步调用完成时做出响应?我需要使用我已经编写的 LINQ 过程将 XML 放入文件中,我需要记录操作的成功或失败,我需要通知用户操作已完成。

  2. 如何确保调用实际上是异步发生的?我记得曾经读过一篇文章,简单地调用异步 SOAP 方法实际上并不会相对于当前线程异步发生除非你先做别的事情。有什么建议吗?

  3. 还有其他我遗漏的主要考虑因素吗?(例如:“如果您忘记这样做,它会破坏您的程序!”)

到目前为止,这些都是我无法找到令人信服的确定答案的问题。提前感谢大家提供的任何帮助。

最佳答案

  1. 您需要在为您自动生成的代理上处理 getRecordsCompleted 事件,如下所示:

    private void Button_Click(object sender, EventArgs e)
    {
    var proxy = new WebServiceProxy();

    // Tell the proxy object that when the web service
    // call completes we want it to invoke our custom
    // handler which will process the result for us.
    proxy.getRecordsCompleted += this.HandleGetRecordsCompleted;

    // Make the async call. The UI thread will not wait for
    // the web service call to complete. This method will
    // return almost immediately while the web service
    // call is happening in the background.
    // Think of it as "scheduling" a web service
    // call as opposed to actually waiting for it
    // to finish before this method can progress.
    proxy.getRecordsAsync("USERNAME", new[] { 1, 2, 3, 4 });

    this.Button.Enabled = false;
    }

    /// <summary>
    /// Handler for when the web service call returns.
    /// </summary>
    private void HandleGetRecordsCompleted(object sender, getRecordsCompletedEventArgs e)
    {
    if (e.Error != null)
    {
    MessageBox.Show(e.Error.ToString());
    }
    else
    {
    record[] result = e.Result;

    // Run your LINQ code on the result here.
    }

    this.Button.Enabled = true;
    }
  2. 如果您在以 Async 结尾的代理上使用自动生成的方法,调用将异步进行 - 仅此而已。在我看来,您需要证明调用是非阻塞(也就是说,UI 线程不必等待它完成),这有点棘手,因为您不能真正将自定义逻辑注入(inject)到自动生成的代码中。从 UI 线程发出的同步调用将阻塞 UI,您的应用程序将变得无响应。如果这没有发生,并且您的 UI 在 Web 服务运行时仍然响应按钮点击、键盘事件等,您可以确定该调用是非阻塞的。显然,这很难证明您的 Web 服务调用是否快速返回。

  3. 您没有显示任何客户端代码,因此很难说您是否遗漏了任何内容。

关于c# - 需要帮助在 C# 4.0 Web 服务客户端中实现异步调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16857765/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com