我想做一個WCF定時器服務,客戶端可以註冊,以便在經過一定時間後從服務中回調。問題是客戶端不會被回叫。不引發異常。基於WCF定時器的服務沒有調用客戶端返回
回調接口是:
[ServiceContract]
public interface ITimerCallbackTarget
{
[OperationContract(IsOneWay = true)]
void OnTimeElapsed(int someInfo);
}
服務看起來像:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Single)]
public class TimerService : ITimerService
private readonly Timer _timer = new Timer(2000); //System.Timers.Timer
public void Subscribe()
{
ITimerCallbackTarget listener =
OperationContext.Current.GetCallbackChannel<ITimerCallbackTarget>();
_timer.Elapsed += (p1, p2) =>
{
listener.OnTimeElapsed(999);
};
_timer.Start();
}
由客戶機使用的回調方法是:
private class TimerCallbackTarget : ITimerCallbackTarget
{
public void OnTimeElapsed(int someInfo)
{
Console.WriteLine(someInfo);
}
}
這樣的客戶端的寄存器:
private static void TestTimerService()
{
InstanceContext callbackInstance = new InstanceContext(new TimerCallbackTarget());
using (DuplexChannelFactory<ITimerService> dcf =
new DuplexChannelFactory<ITimerService>(callbackInstance,
"TimerService_SecureTcpEndpoint"))
{
ITimerService timerProxy = dcf.CreateChannel();
timerProxy.Subscribe();
}
}
如果我使用一個不同的線程在訂閱方法不定時器它的工作原理:
ThreadPool.QueueUserWorkItem(p =>
{
listener.OnTimeElapsed(999);
});
它甚至與定時器(三秒鐘)的作品,如果我把一個了Thread.Sleep( 3000)在訂閱方法的結尾,所以我的猜測是,可能在訂閱方法完成後關閉回調對象的通道被關閉。對於使用OperationContext.Current.GetCallbackChannel()檢索到的回調對象,使用類範圍變量;而不是方法範圍變量沒有幫助。
此前我曾嘗試在定時器服務的定時器的經過事件處理程序中創建新線程,以使其更快。 ObjectDisposedException與消息一起引發:「無法訪問處置的對象。對象名稱:'System.ServiceModel.Channels.ServiceChannel」。然後,我嘗試簡化我的服務,發現即使只使用計時器也會導致上述問題,但我猜這個例外表明與客戶端的回調對象的連接丟失。奇怪的是,如果我沒有在定時器線程中創建新線程,那麼沒有excepiton。回調方法只是不被調用。
您可能需要設置爲「IsOneWay = false」,因爲它是一個雙工系統,不會發生遺忘。 – oleksii