我的第一个WCF服务器 - 为什么OperationContext.Current为null?

时间:2011-09-10 18:08:35

标签: c# wcf

我想要实现我的第一个WCF回叫服务器。这是我的代码:

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ILogCallback))]
public interface ILog
{
}

public interface ILogCallback
{
    [OperationContract(IsOneWay = true)]
    void Push(string callbackValue);
}

public class MyLog : ILog
{

}

class Log
{


    public static void initialize()
    {
        using (ServiceHost host = new ServiceHost(
            typeof (MyLog),
            new Uri[]
                {
                    new Uri("net.pipe://localhost")
                }))
        {

            host.AddServiceEndpoint(typeof (ILog),
                                    new NetNamedPipeBinding(),
                                    "PipeReverse");

            host.Open();
            // TODO: host.Close();
        }
    }

    public static void Push(string s)
    {
        ILogCallback callbacks = OperationContext.Current.GetCallbackChannel<ILogCallback>();
        callbacks.Push(s);
    }
}

然后我尝试使用此代码来使用我的服务器:

        Log.initialize();

        while (true)
        {
            Log.Push("Hello");
            System.Threading.Thread.Sleep(1000);
        }

但我得到了NPE,因为OperationContext.Current为null。为什么,出了什么问题以及如何解决这个问题?

3 个答案:

答案 0 :(得分:14)

因为您不在操作的上下文中。

您只是调用Log类的静态方法。

为了使您处于操作上下文中,您的调用必须来自正在由WCF服务器提供服务的客户端。

答案 1 :(得分:1)

OperationContext.Current是一个线程静态属性,在请求到达服务器时初始化。以下是您调用回调的方法

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ILogCallback))]
public interface ILog
{
  void PushOnTheClient();
}

public class MyLog : ILog
{
  void PushOnTheClient()
  {
        ILogCallback callbacks = OperationContext.Current.GetCallbackChannel<ILogCallback>();
        callbacks.Push(s);
  }
}

答案 2 :(得分:1)

您缺少订阅者的订阅。这样做的方法是在MyLog WCF服务器中创建一个名为“void SendMeLogs()”的[单向]操作。 这将打开客户端回调通道。然后你必须在类似的行中实现SendMeLogs()

void SendMeLogs()
{
  while(CheckLogsForNewData())
 {
   PushOnTheClient();
 }
}

由于SendMeLogs()功能是单向的,客户端不会阻止,但会开始订阅您的日志服务器。 (您可以在网上搜索wcf中双工计算器的示例代码,以获得此架构的一个很好的示例)。  关键是你必须有一个很好的取消订阅方法,如“StopSendingMeLogs”来打破循环,并使PushOnTheClient函数失败安全,以防客户端终止或特定客户端连接中断。  理想情况下,“CheckLogsForNewData”函数应该是您案例中的共享(静态)实现