2017-03-01 5 views
5

私は現在、wcfクライアント経由でアプリケーションを管理しなければならないプロジェクトに取り組んでいます。私が直面している問題は、サーバーにコールした後、コールバックが行われるのを待つクライアントが必要なことです。このシナリオは次のとおりです。wcfクライアントがコールバックを待つようにします

サービスを呼び出して、ウィンドウを表示してから、サーバーアプリケーションがアイドル状態です。ウィンドウ上のボタンをクリックすると、クライアントにコールバックが行われます。その間、クライアントUIは無効にする必要があります。コールバックを待たなければなりません。私はこれをどのように達成できるか教えてください。同時性モードまたは操作コントラクト属性と関係がありますか?

これはのServiceContractとCallbackContractのための私のコードです:

[ServiceContract(CallbackContract = typeof(IWCFServiceCallback))] 
public interface IWCFService 
{ 
    [OperationContract] 
    void OpenWindow(); 
} 
public interface IWCFServiceCallback 
{ 
    [OperationContract(IsOneWay = true)] 
    void ReturnValue(object[] value); 
} 

答えて

0

感謝を構成しているときにコールバックでロックを解除する必要があります。私はWin32 ShowWindow関数を使ってこの問題を解決しました。

1

いいえ、あなたが記述する機能は、同時実行モードまたは運用契約とは何の関係もありません。おそらく、セマフォー(MutexMonitor、何でも...)を使用して機能を実装し、セマフォーを設定するためにサーバーからクライアントにコールバックする必要があります。

あなたが説明している機能は本当に奇妙なようだと言われています。

1

これは、非同期サービス操作を実装し、Async/Awaitを使用して呼び出すことで実行できます。

サービスを呼び出す直前にクライアントUIを無効にしてから、コールバックが戻った後で有効にします。

https://msdn.microsoft.com/en-us/library/ms731177.aspx

using System; 
using System.Collections.Generic; 
using System.ServiceModel; 
using System.Text; 
using System.Threading; 

namespace Microsoft.WCF.Documentation 
{ 
    [ServiceContractAttribute(Namespace="http://microsoft.wcf.documentation")] 
    public interface ISampleService{ 

    [OperationContractAttribute] 
    string SampleMethod(string msg); 

    [OperationContractAttribute(AsyncPattern = true)] 
    IAsyncResult BeginSampleMethod(string msg, AsyncCallback callback, object asyncState); 

    //Note: There is no OperationContractAttribute for the end method. 
    string EndSampleMethod(IAsyncResult result); 

    [OperationContractAttribute(AsyncPattern=true)] 
    IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState); 

    // Note: There is no OperationContractAttribute for the end method. 
    string EndServiceAsyncMethod(IAsyncResult result); 
    } 

    public class SampleService : ISampleService 
    { 
    #region ISampleService Members 

    public string SampleMethod(string msg) 
    { 
     Console.WriteLine("Called synchronous sample method with \"{0}\"", msg); 
     return "The sychronous service greets you: " + msg; 
    } 

    // This asynchronously implemented operation is never called because 
    // there is a synchronous version of the same method. 
    public IAsyncResult BeginSampleMethod(string msg, AsyncCallback callback, object asyncState) 
    { 
     Console.WriteLine("BeginSampleMethod called with: " + msg); 
     return new CompletedAsyncResult<string>(msg); 
    } 

    public string EndSampleMethod(IAsyncResult r) 
    { 
     CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>; 
     Console.WriteLine("EndSampleMethod called with: " + result.Data); 
     return result.Data; 
    } 

    public IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState) 
    { 
     Console.WriteLine("BeginServiceAsyncMethod called with: \"{0}\"", msg); 
     return new CompletedAsyncResult<string>(msg); 
    } 

    public string EndServiceAsyncMethod(IAsyncResult r) 
    { 
     CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>; 
     Console.WriteLine("EndServiceAsyncMethod called with: \"{0}\"", result.Data); 
     return result.Data; 
    } 
    #endregion 
    } 

    // Simple async result implementation. 
    class CompletedAsyncResult<T> : IAsyncResult 
    { 
    T data; 

    public CompletedAsyncResult(T data) 
    { this.data = data; } 

    public T Data 
    { get { return data; } } 

    #region IAsyncResult Members 
    public object AsyncState 
    { get { return (object)data; } } 

    public WaitHandle AsyncWaitHandle 
    { get { throw new Exception("The method or operation is not implemented."); } } 

    public bool CompletedSynchronously 
    { get { return true; } } 

    public bool IsCompleted 
    { get { return true; } } 
    #endregion 
    } 
} 
+0

お返事ありがとうございます。メソッドを呼び出すと、メソッド自体が値を返す場合(コールバックなし)と同じようにクライアントを動作させたい場合 - クライアントはサービスがその作業を完了して値を返すまで待機します。私は手動でUIをロックすることはできません。なぜなら、クライアントはExcelアドインだからです。フォーム/ウィンドウを無効にすることはできません。 – Bartek

+0

ExcelのFunctionWizardが開いている間にサービスの呼び出しが行われるため、Excelがクラッシュするため、セルをロックできません。 – Bartek

+0

@Bartek - これは別の問題ですが、それで別のQ&Aがあります。私はこの質問に対する答えを提供したと信じていますが、私に知らせていないと、私はさらに助けてくれるでしょう。参考にしておきますが、サンプルコードのMicrosoftは、[推奨される命名規則](https://msdn.microsoft.com/en-us/library/mt674882.aspx#Anchor_7)から抜け出しています。非同期関数の名前に「Async」が追加されている必要があります。それにもかかわらず、ここでは 'async'キーワードは表示されませんが、これは非同期アーキテクチャです。 – InteXX

1

concurrenymodeがConcurrencyMode.Singleで、クライアントがサービスを呼び出して、サービスがロックを作成します。 IsOneWayを使用してコールバックインターフェイスを呼び出すと、結果メッセージがサービスに返されます。サービスはロックを再度作成し、クライアントコールからのロックがまだ保持されているためデッドロックになります。 ConsurrencyModeを指定します。リエントラントロックは、コールバックするときにはじめてリリースされ、リターン時に再取得するので、使用することができます。 IsOneWay = trueは、コールバックされたサービスにメッセージが返されないため、解決策です。

だから、あなただけのサービスを呼び出す前に、あなたのGUIをロックすることが可能とコールバック操作はIsOneWay = trueを持っているか、サービスがConcurrencyMode.Reentrantは、あなたの答えを

+0

問題は、クライアントのUIを手動でロックすることができないことです。これは、Excel AddInがFunctionWizardを開いているためです。セルをロックしようとすると、Excelがクラッシュします。 – Bartek

関連する問題