コールバックインターフェイスを実装するクラスは、非同期メソッドも実装する必要があります(インターフェイスで定義されているため)。ただし、インターフェイスに同じメソッドの同期バージョンと同期バージョンの両方がある場合はsynchronous one is invoked by defaultとなります。以下のコードでは、コールバッククラスの非同期操作だけをスローしますが、コードは正常に動作します。
public class StackOverflow_10362783
{
[ServiceContract(CallbackContract = typeof(ICallback))]
public interface ITest
{
[OperationContract]
string Hello(string text);
}
[ServiceContract]
public interface ICallback
{
[OperationContract(IsOneWay = true)]
void OnHello(string text);
[OperationContract(IsOneWay = true, AsyncPattern = true)]
IAsyncResult BeginOnHello(string text, AsyncCallback callback, object state);
void EndOnHello(IAsyncResult asyncResult);
}
public class Service : ITest
{
public string Hello(string text)
{
ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
ThreadPool.QueueUserWorkItem(delegate
{
callback.OnHello(text);
});
return text;
}
}
class MyCallback : ICallback
{
AutoResetEvent evt;
public MyCallback(AutoResetEvent evt)
{
this.evt = evt;
}
public void OnHello(string text)
{
Console.WriteLine("[callback] OnHello({0})", text);
evt.Set();
}
public IAsyncResult BeginOnHello(string text, AsyncCallback callback, object state)
{
throw new NotImplementedException();
}
public void EndOnHello(IAsyncResult asyncResult)
{
throw new NotImplementedException();
}
}
public static void Test()
{
string baseAddress = "net.tcp://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(ITest), new NetTcpBinding(SecurityMode.None), "");
host.Open();
Console.WriteLine("Host opened");
AutoResetEvent evt = new AutoResetEvent(false);
MyCallback callback = new MyCallback(evt);
DuplexChannelFactory<ITest> factory = new DuplexChannelFactory<ITest>(
new InstanceContext(callback),
new NetTcpBinding(SecurityMode.None),
new EndpointAddress(baseAddress));
ITest proxy = factory.CreateChannel();
Console.WriteLine(proxy.Hello("foo bar"));
evt.WaitOne();
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
スレッド「ThreadPool.QueueUserWorkItem(delegate {callback.OnHello(text);});」によってコールバックを呼び出す理由は何ですか?あなたは非同期の 'BeginOnHello'としてどのように呼び出すべきかアドバイスするのがとても親切でしょうか? 'EndOnHello'は命名規則によって呼び出されますか? – g18c