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

感谢您的回复。我会在调用一个方法之后添加一个方法,我希望客户端的行为与方法本身返回值(不带回调)相同 - 客户端一直等到服务完成其工作并返回一个值。我无法手动锁定UI,因为客户端是一个Excel插件,它没有我可以禁用的窗体/窗口。 – Bartek

+0

在Excel打开FunctionWizard时调用服务,所以我不能锁定单元格,因为它会导致Excel崩溃。 – Bartek

+0

@Bartek - 然后,这是一个不同的问题,单独的问答。我相信我已经提供了这个问题的答案,但是如果不让我知道,我会尽力进一步提供帮助。仅供参考请注意,微软在其示例代码中偏离了其自己的[推荐命名约定](https://msdn.microsoft.com/en-us/library/mt674882.aspx#Anchor_7)。异步函数应该在其名称后附加“Async”。当然,我们在这里看不到'async'关键字,但这仍然是一个异步体系结构。 – InteXX

1

当concurrenymode是ConcurrencyMode.Single和客户端调用服务,该服务将创建一个锁。当它使用IsOneWay调用回调接口为false时,结果消息将被发送回服务。该服务将再次创建该锁,并且会因为仍然保持来自客户端调用的锁而导致死锁。 With ConsurrencyMode。可重入的锁定在回拨时会被偷偷地释放,并在返回时重新获取,以便您可以使用该锁定。 IsOneWay = true也是一个解决方案,因为没有结果消息被送回服务回调。

所以,你应该能够锁定你的GUI只调用服务之前,并在回调解锁回调时操作有IsOneWay = true或服务有ConcurrencyMode.Reentrant配置

+0

问题是我无法手动锁定客户端的UI,因为它是打开了FunctionWizard的Excel AddIn。如果我尝试锁定单元格,Excel崩溃。 – Bartek