2

WCF サービスを Windows サービスとして実装しようとしています。数秒間実行される可能性のあるメソッドがいくつかあるため、非同期で呼び出したいと思います。以下雑多。チュートリアル ( MSDNなど) は、実際には機能していないように見えました。少しは動いていますが、サービスからクライアントに返されるデータが期待どおりではありません。サーバー上のサービスのコード例は次のとおりです。

public interface ISomeService
{
    [OperationContract(AsyncPattern = true)]
    IAsnycResult BeginSomeMethod(string someString);

    Collection<string> EndSomeMethod(IAsnycResult asyncresult);
}

[...]

public SomeService : ISomeService
{
    public IAsyncResult BeginSomeMethod(AsyncCallback callback, object state)
    {
        // Do something...
        Collection collection = new Collection<string>{"Some Item", "Another Item"};
        return new CompletedAsyncResult<Collection<string>>(collection);
    }

    public Collection<string> EndSomeMethod(IAsyncResult asyncResult)
    {
        CompletedAsyncResult<Collection<string>> result = 
            asyncResult as CompletedAsyncResult<Collection<string>>;
        if(result != null)
        {
            return result.Data;
        }

        return result;
    }
}

Windows サービスを正常にインストールし、ブラウザ経由で呼び出して WSDL を表示することもできます。「クライアント」プロジェクトへの参照を追加して、それを使用することもできます。プロキシ クラスなどはエラーなしで生成されます。次のようにメソッドを呼び出すこともできます。

[...]
    object async = new object();
    someService.BeginSomeMethod( "Some string", EndSomeMethod, async );        
[...]

コールバック メソッドは次のようになります。

[...]
public static void EndSomeMethod( IAsyncResult asyncResult )
    CompletedAsnycResult<Collection<string>> result = 
        asyncResult as CompletedAsnycResult<Collection<string>>;
[...]

これに続いて、result は null (つまり、キャストが成功しなかった) であり、asyncResult にはいくつかのプロパティとデータが含まれていますが、予期された (または必要な) 文字列コレクションではありません。

編集 サービスメソッドが本来の目的を果たしていることを確認できます(たとえば、ログファイルへの書き込み、ファイルの作成など)。 /編集

さらにいくつかのアプローチを試しましたが、ここで何が間違っているのかについて少し混乱しています。Microsoft から入手できる例は明らかに正しくありません (一部の MSDN ページで読んでいるように)。他にもイベントハンドラーなどの提案をいくつか見つけましたが、今のところそれが最善の方法でしたか?

OperationContract 属性で AsyncPattern = true を使用してサービス メソッドを実際に装飾する必要がありますか? または、VS2010 の機能を使用して、メソッドを非同期的に呼び出すメソッドを生成できますか?

この問題に関して多くの質問があることは承知していますが、この問題に何時間も費やした後、私はかなり立ち往生しているように感じます.

4

3 に答える 3

2

someService.EndSomeMethod(asyncResult)サービスの結果を取得するには、コールバックを呼び出す必要があります。これは、実際には標準の APM パターンの一部です。say a で同じことをしなければならないでしょうFileStream

これに続いて、結果はnullです

はい、CompletedAsnycResultサーバー上にのみ存在するためです。クライアントは、ランタイムによって返される他の型を取得できます。IAsyncResult は、WCF ワイヤー コントラクトの一部ではありません。

実際にasyncResultは、いくつかの WCF 内部クラスのインスタンスになります。

于 2012-09-13T12:24:14.313 に答える
1

WinForm .Net 4.0 で使用するパターンをここに貼り付けます。

//Server WCF
public SomeService
{
    [OperationContract]
    Collection<string> SomeMethod(string someString)
    {
        return new Collection<string>{"Some Item", "Another Item"};
    }
}


//Client
void button_Click(object sender, EventArgs e)
{
    var someService = new TypedServiceReference();
    someService.BeginSomeMethod("Hello", this.someMethodEnded, someService);
}
//will be called once the server reply
void someMethodEnded(IAsyncResult r)
{
    this.Invoke(new MethodInvoker(delegate//The callback is not in the GUI thread
    {
        var someService = (TypedServiceReference) r.AsyncState;//it is the last argument of the BeginSomeMethod() call
        Collection<string> result = someService.EndSomeMethod(r);//Will raise server or network exception (if any)
        this.Text = result.First();
    }));
}
于 2014-08-07T05:35:08.947 に答える
0

これを見ましたか?:

wcf 非同期処理

あなたの例から、「開始」呼び出しが終了する前にすべての作業を行っているように見えます。これは、非同期パターンを学習しているときに見つけたよくある間違いです。

私は WCF でのアプリケーションに精通していませんが、Async モデルは通常、新しいスレッドによって更新される IAsyncResult オブジェクトを使用して新しいスレッドを起動する Begin メソッドです。アクションを「完了する」ために、IsCompleted が true に設定されている場合、元の呼び出し元は、結果を返す対応する End メソッドに元の IAsyncResult オブジェクトを渡す必要があります。簡単な実装は次のようになります。

于 2012-09-13T14:14:15.100 に答える