When does open timeout starts ticking on the WCF service? - wcf

I have set a open timeout property value for my service. I want to know when does this time starts ticking. Is it only when an operation is called and it is processing it and during the idle time after an operation is returned to client.
Does it starts ticking immediately after a channel or proxy is opened using proxy.Open()?
Following is the code -
Client Side -
ProxyClient client = new ProxyClient();
var emp = client.GetEmployee(1);
client.Close();
At the proxy side code is -
class ProxyClient : ClientBase<{Interface}>, {Interface}
{
protected override IEmployee CreateChannel()
{
Thread.Sleep(15000);
return base.CreateChannel();
}
public Employee GetEmployee(int id)
{
var employee = Channel.GetEmployee(id);
return employee;
}
}
Looking at the code above, where exactly the open Timeout tick starts.
The similar question would be answered for closeTimeout also.

Related

Actors ReceiveAsync method unable to POST data to the listener

Background
Notification service has a Notify method which is invoked when an event occurs, so here Im creating the FloorActor and sending the message consisting data and post url to the Actor.
public class NotificationService
{
//HttpClient client = new HttpClient();
ActorSystem notificationSystem = ActorSystem.Create("NotificationSystem");
public void Notify(int clientID, FloorEventData data)
{
try
{
string postUrl = "http://localhost:6001";
FloorData floorData = new FloorData() { Data = data,PostURL=postUrl };
//This commented line of code post data and listener gets the POST request
//client.PostAsJsonAsync<FloorEventData>(postUrl, data);
//Create Floor Actor
var floorActor = notificationSystem.ActorOf<FloorActor>("floorActor");
floorActor.Tell(data);
}
catch (Exception exception)
{
//Log exception
}
}
}
ReceiveAsync method of the Floor Actor data just posts the event data to the specified URL.Framework used to implement Actor Model :Akka.Net
public class FloorActor : ReceiveActor
{
HttpClient client = new HttpClient();
public FloorActor()
{
ReceiveAsync<FloorData>(floorActor => client.PostAsJsonAsync<FloorEventData>(floorActor.PostURL, floorActor.Data));
}
}
Issue-
When I debugged the issue the code flow works as expected:-
1) When event occurs Notify method is invoked
2) Notify method creates the Floor Actor and sends the data
3) Floor Actor's ReceiveAsync method is called and the line of code is executed without any errors or exceptions.But the POST listener, doesn't get the POST data request, so not sure what is happening ?
Tried POST data directly from the Notify method its works, the listener gets the POST request.You can see this code snippet commented above in the Notify method.
So when I try to POST data from my Actor's Receive method, the Http listener does not get the request and there is no errors or exception.
Please let me know if I have to change anything?
ActorSystem should be treated as a singleton for your entire system. So put that instance in a static somewhere and reference it from there.
Also try to await on client.PostAsJsonAsync

wcf callback + save session not operationcontext

I'm new to stackoverflow however I use it everyday. Today I need you because I dont get this info anywhere.
My question is:
I want to make a service with callback to clients but I dont want to callback in the function they call in the service. (something like subscriber/publisher)
I want to save the callback instance.
Then I want a service calling a function in my service that will trigger the callbacks(like this: callbacks.PrintMessage("Message"));)
Saving the callback instance in a static list in a static class.
When calling the callback.function() Im getting this error: "you are using Disposed object"
because Im getting the instance with this: OperationContext.Current.GetCallbackChannel<"callback interface">
What can I do to save that callback instances?
Thanks a lot.
Pedro
CODE:
//FUNCTION IN MY SERVICE
public void Subscribe()
{
var callback = OperationContext.Current.GetCallbackChannel<IMonitoringWebServiceCallback>();
callbacks.Add(callback);
callback = OperationContext.Current.GetCallbackChannel<IMonitoringWebServiceCallback>();
AlarmCallbackSingleton.Instance.AddCallback(callback);
//callback.PrintString("String"); //HERE IT WORKS! BUT I DONT WANT CALL HERE!
alarmInfoHandler = new AlarmInfoEventHandler(AlarmInfoHandler);
NewAlarmInfo += alarmInfoHandler;
}
//FUNCTION IN THE SAME SERVICE CALLED BY OTHER CLIENT
public void PublishAlarm(string alarm)
{
AlarmInfoEventArgs e = new AlarmInfoEventArgs();
e.Alarm = alarm;
NewAlarmInfo(this, e);
}
public void AlarmInfoHandler(object sender, AlarmInfoEventArgs e)
{
List<IMonitoringWebServiceCallback> callbacks = AlarmCallbackSingleton.Instance.GetCallbacks();
//EVERYONE THAT SUBSCRIBED SHOULD EXECUTE THIS (HERE I GET THE DISPOSED ERROR)
callbacks.ForEach(x => x.ShowString("String!"));
}
Ok. I got it! The answer to this question is as simple as this:
When you subscribe to the service you need to save somewhere(List etc..) the OperationContext and not the callback object.
Then when the PublishAlarm is called by another client the event is triggered and you need to get OperationContext of all clients that subscribe.
I saved that objetcs in a static List(singleton class) just for the example.
Then:
public void AlarmInfoHandler(object sender, AlarmInfoEventArgs e)
{
var operation = AlarmCallbackSingleton.Instance.operationContext
var callback = operation.GetCallbackChannel<IMonitoringWebServiceCallback>();
callback.ShowAlarm(); //function you want to call
}
Hope this can help!

WCF duplex requests time delay

I have an simple Pub/Sub service built on WCF. the interface of server side looks like below:
[ServiceBehavior(UseSynchronizationContext = false, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class RDFService : IRDFService
{
public Guid Register(string ric)
public void Unregister(Guid guid)
}
Client side call back interface:
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
internal class ServiceCallback : IRDFCallBack
{
// [OperationContract(IsOneWay = true)]
public void UpdateSignal(Guid guid, string ric, MarketFeedData data, MarketDataMessageType type)
}
Client side is an Win form project.
The handling logic is as below:
If client receives an UpdateSignal request, withing the handling method, client will make an call to unregister it self.
Usually, both UpdateSignal and Unreg methods takes almost no time. But when an influx(8-10) of UpdateSignal requests are sent to client concurrently, there's a significant delay between 1-3 seconds. I opened trace and found that the time are held on the Unregister service method call:
As in the picture, there's an 2 seconds delay between activity 3 and 4. What can be the cause? Thanks.

System.ServiceModel.ClientBase connected to Service

I have the following code:
public partial class MyServiceClient : System.ServiceModel.ClientBase<...
if (m_MyClient == null)
m_MyClient = new MyServiceClient
("BasicHttpBinding_IMyService", remoteAddress);
WriteOutput("Successfully connected to service");
My question is how do i know that my client actually connected to the service at this point? I would like to display a message of either failure or success.
When you've created the client, and no exception like EndpointNotFoundException has occured - then you are "connected" to the service which really means: the communication channel between the client and the service is ready to be used for sending messages back and forth. That's all there is - there's nothing on the server side yet to really handle your calls (except for the channel listener which will get activated if a message arrives).
You can also check the client channel's .State property - ideally, it should be Opened at that point:
Use this if you're deriving from ClientBase<T>
m_MyClient.State == CommunicationState.Opened
or this is you're using the standard client class generated by the Add Service Reference functionality in Visual Studio:
(m_MyClient as IClientChannel).State == CommunicationState.Opened
After realizing what i mentioned in my above comment, i realized the answer to my question was as follows:
In my ServiceContract i added the following:
[OperationContract]
bool IsAlive();
Whose implentation simply looks as follows:
public bool IsAlive()
{
return true;
}
Then changed my code as follows:
m_MyClient = new MyServiceClient("BasicHttpBinding_IMyService", remoteAddress);
try
{
m_MyClient.IsAlive();
}
catch (EndpointNotFoundException)
{
WriteOutput("Unable to connect to service");
m_MyClient = null;
}
if (m_MyClient != null)
WriteOutput("Successfully connected to service");

How to implement IsOneWay=true in WCF nettcpBinding

How can I implement one way WCF operations?
I just tried using IsOneWay attribute as:
[OperationContract(IsOneWay=true)]
void MethodName(string param1, int param2)
Is there any other change I need to make or any specific change in app.config?
FYI, my WCF service implements netTcpBinding, though I think that shouldn't make any difference.
As shown, your code looks ok. There should be no problem with doing one-way calls with netTcpBinding.
If you're interested, chapter 5 in Juval Lowy's awesome Programming WCF Services 2nd Edition contains a good bit of information about one-way services.
From what you've shown, so far though I don't see anything wrong. Please give us some more details.
We had a problem with one-way calls not returning immediately using the NetTcpBinding. This blog post identifies the problem and provides a solution.
http://blogs.msdn.com/b/distributedservices/archive/2009/02/12/client-proxy-close-method-call-does-not-finish-immediately-in-one-way-wcf-calls.aspx
From the article:
Problem: Clients calling a one-way method in WCF Service and then close method on proxy does not return until the call is actually finished or call times out. Ever wonder why this happens?
Cause: When you specify “One-Way” on your interface, the underlying channel operation is still two-way since the one way binding element is not in the channel stack. Thus, the close operation gets blocked until the one way operation completes.
This is by design and the development team is working to change it in future versions of .Net framework.
...
Solution (Work around):
Layer the OneWayBindingElement on top of netTcpBinding as shown in the below code. This way, close call on proxy will return immediately and eventually the one-way call will return in fire and forget fashion.
[ServiceContract]
public interface IService1
{
[OperationContract(IsOneWay = true)]
void SetData(int value);
}
public class Service1 : IService1
{
public void SetData(int value)
{
//Application specific code
}
}
Service Host code:
Form1ServiceHost = new ServiceHost(this, new Uri("net.tcp://localhost:8091/WindowsFormApp/Form1/"), new Uri("http://localhost:8090/WindowsFormApp/Form1/"));
Binding binding = new NetTcpBinding();
BindingElementCollection oldBindingElements = binding.CreateBindingElements();
BindingElementCollection bindingElements = new BindingElementCollection();
bindingElements.Add(new OneWayBindingElement());
foreach (BindingElement bindingElement in oldBindingElements)
{
bindingElements.Add(bindingElement);
}
binding = new CustomBinding(bindingElements);
Form1ServiceHost.AddServiceEndpoint("WCFServiceLibrary.IService1", binding, "");
Form1ServiceHost.Open();
Client Code:
Binding binding = new NetTcpBinding();
BindingElementCollection oldBindingElements = binding.CreateBindingElements();
BindingElementCollection bindingElements = new BindingElementCollection();
bindingElements.Add(new OneWayBindingElement());
foreach (BindingElement bindingElement in oldBindingElements)
{
bindingElements.Add(bindingElement);
}
binding = new CustomBinding(bindingElements);
Service1Client client = new Service1Client(binding, new EndpointAddress("net.tcp://localhost:8091/WindowsFormApp/Form1/"));
client.SetData(10);
Console.WriteLine("set data");
Console.WriteLine("Now closing the channel,Before close, current time is {0}", DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString());
client.Close();
Console.WriteLine("Now closing the channel,After close, current time is {0}", DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString());`