Asynchronous WCF callback method
-
Hi I'm developing a WCF service, which defines a callback contract through which the server can call a method on the client. Below is a sample code:
\[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = (typeof(ISampleServiceCallback)))\] public interface ISampleService { \[OperationContract(IsInitiating = true, IsTerminating = false, IsOneWay = false)\] bool Register(int controllerId); \[OperationContract(IsInitiating = false, IsTerminating = true, IsOneWay = true)\] void Unregister(); } \[ServiceContract\] public interface ISampleServiceCallback { \[OperationContract(IsOneWay = false)\] bool ReceiveMessage(string message); }
The problem arises when the client on exit fails to call the Unregister() method - becouse of a crash or something, so the server still has the reference to the client's callback channel. When the server calls the ReceiveMessage method on the client, that method blocks for the time specified by the "sendTimeout" in the app.config before throwing an exception. I tried using the following approach to call the callback method
public delegate bool ReceiveDelegate(string message);
public void NotifyClient(string message)
{
ReceiveDelegate receiver = new ReceiveDelegate(_callback.ReceiveMessage); //_callback is a reference to the callback channel
receiver.BeginInvoke(message, new AsyncCallback(onReceiveCompleted), receiver);
}private void onReceiveCompleted(IAsyncResult result)
{
bool ok = false;
try
{
ok = ((ReceiveDelegate)result.AsyncState).EndInvoke(result);
}
catch(Exception ex)
{
string error = ex.Message;
}
}In the example above, the receiver.BeginInvoke() still blocks the calling thread - which is wird becouse when I tried calling another long-lasting function the same way and the call to BeginInvoke did not block. So my question is: How can I define and implement the ReceiveMessage method as asynchronous, so it will not block the calling thread. Any idea will be appreciated Uros
-
Hi I'm developing a WCF service, which defines a callback contract through which the server can call a method on the client. Below is a sample code:
\[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = (typeof(ISampleServiceCallback)))\] public interface ISampleService { \[OperationContract(IsInitiating = true, IsTerminating = false, IsOneWay = false)\] bool Register(int controllerId); \[OperationContract(IsInitiating = false, IsTerminating = true, IsOneWay = true)\] void Unregister(); } \[ServiceContract\] public interface ISampleServiceCallback { \[OperationContract(IsOneWay = false)\] bool ReceiveMessage(string message); }
The problem arises when the client on exit fails to call the Unregister() method - becouse of a crash or something, so the server still has the reference to the client's callback channel. When the server calls the ReceiveMessage method on the client, that method blocks for the time specified by the "sendTimeout" in the app.config before throwing an exception. I tried using the following approach to call the callback method
public delegate bool ReceiveDelegate(string message);
public void NotifyClient(string message)
{
ReceiveDelegate receiver = new ReceiveDelegate(_callback.ReceiveMessage); //_callback is a reference to the callback channel
receiver.BeginInvoke(message, new AsyncCallback(onReceiveCompleted), receiver);
}private void onReceiveCompleted(IAsyncResult result)
{
bool ok = false;
try
{
ok = ((ReceiveDelegate)result.AsyncState).EndInvoke(result);
}
catch(Exception ex)
{
string error = ex.Message;
}
}In the example above, the receiver.BeginInvoke() still blocks the calling thread - which is wird becouse when I tried calling another long-lasting function the same way and the call to BeginInvoke did not block. So my question is: How can I define and implement the ReceiveMessage method as asynchronous, so it will not block the calling thread. Any idea will be appreciated Uros
How about placing the call in finally block? Here is how I call service asynchronously:
private void btnAsyncCall_Click(object sender, EventArgs e) {
ServiceClient oAsyncProxy = new ServiceClient();
IAsyncResult oAsyncGet;
for (int i = 0; i < 10; i++) {
oAsyncGet = oAsyncProxy.BeginGet("Whatever!", GetCallBack, oAsyncProxy);
Interlocked.Increment(ref counter);while (counter > 0) { Thread.Sleep(1000); } } oAsyncProxy.Close(); } static void GetCallBack(IAsyncResult oAsyncResult) { string s = ((ServiceClient)oAsyncResult.AsyncState).EndGet(oAsyncResult).ToString(); Interlocked.Decrement(ref counter); }
I hope this helps you.
50-50-90 rule: Anytime I have a 50-50 chance of getting something right, there's a 90% probability I'll get it wrong...!!
modified on Sunday, December 13, 2009 9:53 PM
-
How about placing the call in finally block? Here is how I call service asynchronously:
private void btnAsyncCall_Click(object sender, EventArgs e) {
ServiceClient oAsyncProxy = new ServiceClient();
IAsyncResult oAsyncGet;
for (int i = 0; i < 10; i++) {
oAsyncGet = oAsyncProxy.BeginGet("Whatever!", GetCallBack, oAsyncProxy);
Interlocked.Increment(ref counter);while (counter > 0) { Thread.Sleep(1000); } } oAsyncProxy.Close(); } static void GetCallBack(IAsyncResult oAsyncResult) { string s = ((ServiceClient)oAsyncResult.AsyncState).EndGet(oAsyncResult).ToString(); Interlocked.Decrement(ref counter); }
I hope this helps you.
50-50-90 rule: Anytime I have a 50-50 chance of getting something right, there's a 90% probability I'll get it wrong...!!
modified on Sunday, December 13, 2009 9:53 PM
Hi Thank you for your reply. I am afraid I don't quite understand your answer. What is a ServiceClient? I think you didn't understand my question. This is on the server(service) side, of the distributed app. not on the client, so there is no ServiceClient! I am trying to execute the callback method, using the async pattern. The call to the callback method is placed in the try-catch block because in case the client is not present any more, the call to that method throws an exception, so placing the call to the finnaly block would crash the program. Uros