2

だから私はWebサービスを消費するクライアントに取り組んでいます。サービスの WSDL ファイルと XSD ファイルを使用してプロキシ クラスを生成したところ、すべての同期関数が正常に動作しました。ただし、同期の性質上、いずれかの呼び出しを行うと、UI は呼び出しが完了するまで応答を停止します。非同期メソッドを使用する典型的な理由ですよね?

問題は、私はまだ学位を取得するために学校に通っていて、非同期プログラミングについてほとんど知らないことです。私はそれをオンラインで読み込もうとしましたが (私の雇用主は 24 時間 365 日ブックスを定期購読しています)、どのように電話をかけるべきか、どのように応答するべきかを理解するのに苦労しています。ここに私が持っているものがあります:

    /// <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. 私が見逃している他の主要な考慮事項はありますか? (たとえば、「これを忘れると、プログラムが壊れてしまいます!」)

これらはすべて、これまでのところ説得力のある確固たる答えを見つけることができなかった質問です. どうぞよろしくお願いいたします。

4

2 に答える 2

4
  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 スレッドが完了するまで待機する必要がないこと) であり、カスタム ロジックを実際に挿入できないため、これは少し注意が必要です。自動生成されたコードに。UI スレッドから同期呼び出しを行うと、UI がブロックされ、アプリケーションが応答しなくなります。これが発生せず、Web サービスの実行中に UI がボタンのクリックやキーボード イベントなどに応答する場合は、呼び出しがブロックされていないことを確認できます。明らかに、Web サービス呼び出しがすぐに返されるかどうかを証明するのは難しいでしょう。

  3. クライアントコードを表示していないため、何か不足しているかどうかを判断するのは困難です。

于 2013-05-31T16:04:42.323 に答える