2017-03-01 2 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

아니, 당신이 설명하는 기능은 동시성 모드 또는 운영 계약과는 아무 상관이 없습니다. 세마포어 (Mutex, Monitor, 뭐든간에 ...)를 사용하여 기능을 구현하고 세마포어를 설정하기 위해 서버에서 클라이언트로 콜백해야합니다.

당신이 묘사 한 기능이 정말 이상한 것처럼 보였습니다.

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

답장을 보내 주셔서 감사합니다. 메소드를 호출 한 후 메서드를 호출 한 후 메서드 자체가 콜백없이 값을 반환하는 것처럼 클라이언트가 동일한 방식으로 작동하게하려는 경우 - 클라이언트는 서비스가 작업을 완료하고 값을 반환 할 때까지 기다립니다. 클라이언트가 수동으로 잠글 수 없습니다. Excel 부가 기능은 양식/창이 없기 때문에 사용할 수 없습니다. – Bartek

+0

Excel에 FunctionWizard가 열려있는 동안 서비스 호출이 이루어 지므로 Excel이 손상되기 때문에 셀을 잠글 수 없습니다. – Bartek

+0

@Bartek - 그건 다른 문제이고, 그렇다면 별도의 질의 응답입니다. 나는이 질문에 답을 주었다고 믿지만, 알려주지 않으면 더 멀리 도우려고 노력할 것이다. 참고로 여기에있는 샘플 코드의 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 = 사실이 있거나 서비스가 ConcurrencyMode.Reentrant 귀하의 답변을

+0

문제는 클라이언트의 UI를 수동으로 잠글 수 없다는 것입니다. 이는 FunctionWizard가 열린 Excel AddIn이기 때문입니다. 셀을 잠그면 Excel이 충돌합니다. – Bartek