0

WCF既存のアプリケーションに組み合わせる必要のあるサービスがあります。
サービスのインターフェース:

[ServiceContract(CallbackContract = typeof(IClientCallback))]
    public interface IExecutionService
    {
        [OperationContract]
        ExecutionStatus Execute(string path);

        [OperationContract]
        ExecutionStatus Abort();
    }

そしてコールバック:

[ServiceContract]
    public interface IClientCallback
    {
        [OperationContract(IsOneWay = false)]
        string GetUserInput(string message, string information, bool isPause);

        [OperationContract(IsOneWay = true)]
        void OutputAvailable(OutputAvailableEventArgs args);

        [OperationContract(IsOneWay = true)]
        void ResultAvailable(ResultAvailableEventArgs args);

        [OperationContract(IsOneWay = true)]
        void ExecutionStarted(ExecutionStartedEventArgs args);

        [OperationContract(IsOneWay = true)]
        void ExecutionEnded(ExecutionEndedEventArgs args);
    }

報告するものがある場合、サービスはいくつかの作業と報告を実行しています。ArgsクラスはDataContract、名前空間としてマークされています。.Netネイティブタイプ(、、)が含まれてintstringますDateTime

テストアプリケーションを作成しましたが、すべてがうまく機能しています(サービスの実行を要求してから、ExecutionStarted約1秒と呼ばれるまでの時間)。

既存のアプリケーションでクライアントを作成する場合、2つの問題があります。

  1. Execute()遅さ-からまで約1分ExecutionStarted()
  2. 最後の呼び出しExecutionEnded---ただ起こりません。どうなりますか?代わりに最後のOutputAvailable呼び出しが発生します。デバッグ中に、サービスがExecutionEndedメソッドを呼び出しているのがわかりますが、クライアント側で呼び出されるのはOutputAvailable(finishメソッドの代わりではなく、以前にのみ呼び出されるべきでした)です。

テストクライアントと実際のアプリケーションで同じテストを使用しています。

役立つかもしれないいくつかのコード、私は願っています:

サービス

クラス宣言:

  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)]
        public class ExecutionService : IExecutionService

public ExecutionStatus Execute(string path)
        {
            lock (locker)
            {
                var tempClient = OperationContext.Current.GetCallbackChannel<IClientCallback>();
                if (client == null)
                    client = tempClient;
                else if (client != null && client != tempClient)
                {
                    throw new FaultException(new FaultReason("Execution Service is busy processing a request."));
                }
                else if (tempClient == null)
                    throw new FaultException(new FaultReason("No client found, execution is aborted."));
                Log.InfoFormat("client: "+ DateTime.Now);
                Log.InfoFormat(client == null ? "null" : client.ToString());
            }
            ((IContextChannel)client).OperationTimeout = new TimeSpan(0,3,0);
            Task<ExecutionStatus> executionTask = Task.Factory.StartNew(() => HandleExecution(path));
            return executionTask.Result;
}

(一度に1つのクライアントしかないことを確認します。サービスのメソッド中にコールバックを使用できるように、再入可能モードが必要です。)

クライアント: サービスへの接続を作成します。

 var myBinding = new WSDualHttpBinding();
 var myEndpoint = new EndpointAddress("http://localhost:3050/ExecutionService");
 var myChannelFactory = new DuplexChannelFactory<IExecutionService>(this, myBinding, myEndpoint);
 service = myChannelFactory.CreateChannel();
 var executionStatus = service.Execute(@"C:\Users\nosh\Desktop\launcher.py"); 

必要に応じて、さらにコードを公開します。
もう1つの問題は、実際のアプリでは次のようになることです。

A first chance exception of type 'System.TimeoutException' occurred in System.ServiceModel.dll
A first chance exception of type 'System.TimeoutException' occurred in mscorlib.dll

'execute'メソッドが戻る直前、および後で次のようになります。

A first chance exception of type 'System.Runtime.Serialization.SerializationException' occurred in System.Runtime.Serialization.dll
A first chance exception of type 'System.ServiceModel.Dispatcher.NetDispatcherFaultException' occurred in System.ServiceModel.dll
A first chance exception of type 'System.ServiceModel.Dispatcher.NetDispatcherFaultException' occurred in System.ServiceModel.dll
A first chance exception of type 'System.ServiceModel.Dispatcher.NetDispatcherFaultException' occurred in System.ServiceModel.dll
A first chance exception of type 'System.ServiceModel.Dispatcher.NetDispatcherFaultException' occurred in System.ServiceModel.dll

これは私のテストアプリケーションでは発生しません。
ここで何が問題なのか分かりますか?

編集
私はそれを修正する方法ではなく、何が悪いのかを知っていると思います。問題は、私の実際のアプリがでWPFあり、での動作にいくつかの問題があることWCFです。に切り替えてみましたNetTcpBindingが、うまくいきませんでした。他の提案をいただければ幸いです。

編集2
このWPF問題については、コールバックの実装に以下を追加する必要があります。

[CallbackBehavior(UseSynchronizationContext = false)]

ここで答えを提供してくれたIan Ringroseに感謝します。) 今でも応答しないクライアントに直面していますが、サービスへの接続がハングしません。もっと提案をいただければ幸いです。
WPF

編集3
これで、クライアントで呼び出されていないのは1つのメソッドだけになります。接続は有効であり(その後に他の呼び出しがあります)、メソッドは特別なことを何もしていません。

4

2 に答える 2

0

サービスの設定方法はわかりませんが、サービスの呼び出しに非同期メソッドを使用していますか?それ以外の場合は、それを実装することをお勧めします。サービスは静的であるため、他のデバイスで実行するとリンクが機能しないという問題も発生する可能性があります。シリアル化エラーについては仕方がありません。

于 2013-03-27T13:56:14.227 に答える
0

私は誰もが時々それらのWTFにつまずく必要があると思います。
ソリューションの背後にあるロジックを説明することはできませんが、ソリューション自体は十分に単純です。

  1. サービスソリューションで、問題のあるメソッドの名前を(ICallbackインターフェイスで)変更します。
  2. 問題のあるアプリケーションを再コンパイルし、更新して再コンパイルします。
  3. アプリケーションを実行すると、メソッドが突然呼び出されます。
  4. メソッドの名前を元の名前に再度変更します。
  5. 勝つ!
于 2013-04-02T13:58:49.837 に答える