我想要实现我的第一个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。为什么,出了什么问题以及如何解决这个问题?
答案 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
”函数应该是您案例中的共享(静态)实现