WCF асинхронный обратный вызов
Я успешно реализовал шаблон обратного вызова WCF в своем коде, и теперь я хочу реализовать асинхронный обратный вызов. Вот мой код интерфейса:
[ServiceContract(Name = "IMessageCallback")]
public interface IMessageCallback
{
[OperationContract(IsOneWay = true)]
void OnMessageAdded(string message, DateTime timestamp);
}
[ServiceContract(Name="IMessageCallback")]
public interface IAsyncMessageCallback
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginOnMessageAdded(string msg, DateTime timestamp, AsyncCallback callback, object asyncState);
void EndOnMessageAdded(IAsyncResult result);
}
[ServiceContract(CallbackContract = typeof(IMessageCallback))]
public interface IMessage
{
[OperationContract]
void AddMessage(string message);
}
Чтобы использовать синхронный обратный вызов, я объявил свой канал и конечную точку следующим образом:
DuplexChannelFactory<IMessage> dcf = new DuplexChannelFactory<IMessage>(new InstanceContext(this), "WSDualHttpBinding_IMessage");
<endpoint address="net.tcp://localhost:8731/Message/"
binding="netTcpBinding"
contract="WCFCallbacks.IMessage" name="WSDualHttpBinding_IMessage">
У меня проблемы с получением правильной комбинации конечной точки и канала для использования асинхронного обратного вызова. Может ли кто-нибудь указать мне правильное направление?
Кроме того, когда выполняется следующая строка кода:
OperationContext.Current.GetCallbackChannel<IAsyncMessageCallback>();
Я получаю следующую ошибку:
Unable to cast transparent proxy to type 'WCFCallbacks.IAsyncMessageCallback'
1 ответ
Решение
Необходимо изменить свойство CallbackContract IMessage контракта на обслуживание для этого типа (IAsyncMessageCallback). Пример ниже работает с асинхронным обратным вызовом.
public class Stackru_5979252
{
[ServiceContract(Name = "IMessageCallback")]
public interface IAsyncMessageCallback
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginOnMessageAdded(string msg, DateTime timestamp, AsyncCallback callback, object asyncState);
void EndOnMessageAdded(IAsyncResult result);
}
[ServiceContract(CallbackContract = typeof(IAsyncMessageCallback))]
public interface IMessage
{
[OperationContract]
void AddMessage(string message);
}
[ServiceBehavior(IncludeExceptionDetailInFaults = true, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : IMessage
{
public void AddMessage(string message)
{
IAsyncMessageCallback callback = OperationContext.Current.GetCallbackChannel<IAsyncMessageCallback>();
callback.BeginOnMessageAdded(message, DateTime.Now, delegate(IAsyncResult ar)
{
callback.EndOnMessageAdded(ar);
}, null);
}
}
class MyClientCallback : IAsyncMessageCallback
{
public IAsyncResult BeginOnMessageAdded(string msg, DateTime timestamp, AsyncCallback callback, object asyncState)
{
Action<string, DateTime> act = (txt, time) => { Console.WriteLine("[{0}] {1}", time, txt); };
return act.BeginInvoke(msg, timestamp, callback, asyncState);
}
public void EndOnMessageAdded(IAsyncResult result)
{
Action<string,DateTime> act = (Action<string,DateTime>)((System.Runtime.Remoting.Messaging.AsyncResult)result).AsyncDelegate;
act.EndInvoke(result);
}
}
static Binding GetBinding()
{
return new NetTcpBinding(SecurityMode.None);
}
public static void Test()
{
string baseAddress = "net.tcp://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IMessage), GetBinding(), "");
host.Open();
Console.WriteLine("Host opened");
InstanceContext instanceContext = new InstanceContext(new MyClientCallback());
DuplexChannelFactory<IMessage> factory = new DuplexChannelFactory<IMessage>(instanceContext, GetBinding(), new EndpointAddress(baseAddress));
IMessage proxy = factory.CreateChannel();
proxy.AddMessage("Hello world");
Console.Write("Press ENTER to close the host");
Console.ReadLine();
((IClientChannel)proxy).Close();
factory.Close();
host.Close();
}
}