WCF events in server-side - wcf

I'm working on an application in WCF and want to receive events in the server side.
I have a web that upon request needs to register a fingerprint.
The web page request the connection of the device and then every second for 15 seconds requests the answer.
The server-side code is apparently "simple" but doesn't work.
Here is it:
[ServiceContract]
interface IEEtest
{
[OperationContract]
void EEDirectConnect();
}
class EETest : IEEtest
{
public void EEDirectConnect()
{
CZ ee = new CZ(); // initiates the device dll
ee.Connect_Net("192.168.1.200", 4011);
ee.OnFinger += new _IEEEvents_OnFingerEventHandler(ee_OnFinger);
}
public void ee_OnFinger()
{
//here i have a breakpoint;
}
}
every time I put my finger, it should fire the event. in fact if I
static void Main()
{
EETest pp = new EETest();
pp.EEDirectConnect();
}
It works fine. but from my proxy it doesn't fire the event.
do you have any tips, recommendations, or can you see the error?
Thanks everyone.

I can see two issues with your code, which may or may not be the problem.
A) Event Registration Race Condition
You call CZ.Connect_Net() and THEN you register with the event handler. So if your event fires between calling Connect_Net() and you registering a method to handle the event then you'll not see it. Register the event handler first and then call Connect_Net().
B) EEtest lifetime.
The life time of your EEtest class depends on the Instancing Mode you use in WPF, see http://mkdot.net/blogs/dejan/archive/2008/04/29/wcf-service-behaviors-instance-and-concurrency-management.aspx. Generally the default is Per-Call which means a new instance of EEtest is created just to service the call to EEDirectConnect. So when you invoke the method EEDirectConnect you get this:
EEDirectConnect invocation started.
WCF makes a new EEtest class.
WCF invokes the method on EEtest.
The method news up a CZ and invokes the Connect-net method.
The event handler is attached.
The method EEDirectConnect completes.
EEtest is now "unrooted" by WCF - it's eligible for GC, and hence CZ is eligible for GC.
So perhaps it takes a very short time (or it's synchronous) and the problem is A, or it's asynchronous and it takes a little bit longer and it's B.
BTW: To fix B you could use some sort of synchronisation mechanism (eg an Event) to block until ee_Onfinger fires.

Related

Is it better to use the Bus Start method or a class constructor to instantiate objects used by a service

I'm using nServiceBus 5 and have created a number of host endpoints, two of which listen for database changes. (The specifics of how to do this can be found here). The intention is to have a service running in the background which publishes an event message using the Bus when notified to do so by the database listener.
The code which creates the database listener object and handles events is in the Start method, implemented as part of IWantToRunWhenBusStartsAndStops.
So - Is putting the code here likely to cause problems later on, for example if an exception is thrown (yes, I do have try/catch blocks, but I removed them from the sample code for clarity)? What happens when the Start method finishes executing?
Would I be better off with a constructor on my RequestNewQuoteSender class to instantiate the database listener as a class property and not use the Start method at all?
namespace MySample.QuoteRequest
{
public partial class RequestNewQuoteSender : IWantToRunWhenBusStartsAndStops
{
public void Start()
{
var changeListener = new DatabaseChangeListener(_ConnectionString);
// Assign the code within the braces to the DBListener's onChange event
changeListener.OnChange += () =>
{
// code to handle database change event
changeListener.Start(_SQLStatement);
};
// Now everything has been set up.... start it running.
changeListener.Start(_SQLStatement);
}
public void Stop() { LogInfo("Service Bus has stopped"); }
}
}
Your code seems fine to me.
Just a few small things:
Make changeListener a class field, so that it won't be GC (not 100% sure if it would be but just to make sure);
Unsubscribe from OnChange on the Stop() method;
You may also want to have a "lock" around changeListener.Start(_SQLStatement); and the Stop so that there are no racing conditions (I leave that one up to you to figure out if you need it or not);
Does this make sense ?

Can't Seem to call server methods in SignalR

I've been working with SignalR with MVC4 for a few weeks and have been successful for the most part when it comes to simple setups. I've had no problems sending out messages to all clients from the server with one page setups and a hub.
The current project I'm working on, I'm trying to use groups, so after I start the client connection, I try to make a call to the server like so.
in my _Layout.cshtml
var dashboardhub;
$(document).ready(function () {
dashboardhub = $.connection.dashboardHub;
dashboardhub.client.connect = function () { };
window.hubReady = $.connection.hub.start();
});
in my Index.cshtml
window.hubReady.done(function () {
dashboardhub.server.addGroup('#ViewContext.RouteData.Values["area"].ToString()');
}).fail(function () {
console.log('connection failed');
});
In my DashboardHub class
public class DashboardHub : Hub {
/// <summary>
/// Constructor
/// </summary>
public DashboardHub() {
}
public void AddGroup(string group) {
this.Groups.Add(Context.ConnectionId, group);
}
}
When dashboardhub.server.addGroup is fired on the client side, I never see it hit the server method AddGroup. This is obviously making it difficult to create groups.
It's very possible I'm missing something, but I'm not totally sure what that might be. Any pointers would be very much appreciated.
EDIT: Sorry for the pointless post. There was something in the hub constructor that was throwing an exception, but it was very much not apparent. Obviously it's not in the code I posted, but basically, I had added a PropertyChanged event handler on an object that was null in the constructor. This basically broke the entire hub, which didn't allow server calls.
Sorry for the pointless post. There was something in the hub constructor that was throwing an exception, but it was very much not apparent. Obviously it's not in the code I posted, but basically, I had added a PropertyChanged event handler on an object that was null in the constructor. This basically broke the entire hub, which didn't allow server calls.

Timer inside a WCF Singleton hosted in a Windows Service (over webHttpBinding) dies unexpectedly

I have a WCF service hosted in a Windows Service (running under Local System). I am running a System.Timer inside it. The Operation o1, that initializes the Timer, is declared over a http endpoint over webHttpBinding.
I enabled tracing for System.ServiceModel and from the .svcLog file I checked the Listen Duration for the Operation o1. It shows that, after running for approx 20 hours the Listening at the http endpoint just stops.
I think the this due to the fact that no incoming message arrived at that endpoint. The issue here is with the Listening coming to a stop, my timer(which was initialized inside that particular Operation o1) also stops!
Is there a recommended way to keep the Listener, and hence the timer, up for long durations?
Can we periodically ping the o1 Operation to keep it in memory?
Also, my timer variable that I initialize inside the Operation o1 is an instance variable, isn't this variable expected to be in memory (the WCF being a Singleton) even if the Listener closes??
Thanks so much.
Code Exceprts-
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class SchedulerWindows : ISchedulerWindows
{
///.........all instance variables.....
DataTimer timer = null; /**DataTimer wraps a System.Timers timer variable**/
public List<DataTimer> timersInService = new List<DataTimer>();
public ISchedulerWindows.o1(string s1, string s2, /*********/)
{
//..........//
timer = new DataTimer();
}
}
public class DataTimer
{
/****Newly introduced System.Threading.Timer, previously I was using System.Timers.Timer which was dying****/
public System.Threading.Timer thTimer;
private static readonly object dbAccessLock = new object();
private static readonly object thCallbackLock = new object();
public DataTimer()
{
}
public DataTimer(/************/)
{
TimerCallback timerDelegate = new TimerCallback(this.WorkMethod);
EventLogLogger l = new EventLogLogger();
//l.LogMessage("setting up timer ");
thTimer = new Timer(this.WorkMethod, null, 0, period);
}
...
}
EDIT: Changing to System.Threading namespace from System.Timers namespace AND increasing the timed interval fixed it for me. The timer variable doesn't disappear anymore.
The most likely cause for your issue is InstanceContextMode. If you want your service instance to always be in memory you should use Single. You probably have PerSession or PerCall and that would explain why your timer is disappearing. You mention that your service is singleton but the symptoms are very suspicious. The service instance stays in memory until you shutdown host.
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.Single
)]
From WCF instance management:
The singleton service lives forever, and is only disposed of once the
host shuts down. The singleton is created exactly once when the host
is created.
EDIT: You probably checked that windows service is still running when your listener stops listening and timer disappears. It would also make sense to see if ServiceHost itself stays in memory. You can also put some logging in ServiceHosts 'Closing', 'Closed' and 'Faulted' event handlers.
EDIT 2:
If your timer is disappearing than you should look at how you allocate it. It most likely gets garbage collected. You have to declare it as an instance field that is reachable from live objects. Make it static to be absolutely sure. You do it for DataTimer but it is not clear how the timer is declared and allocated inside DataTimer. Post some code please.
EDIT 3:
You should not create timers in the operation. What happens if operation get called more than once? What happens to the old timer? I don't see how you close/dispose it. You also seem to have two constructors for DataTimer. One of them is doing nothing. And on top of that you have separate list of timers. This is a bit convoluted. Please isolate the problem and maybe post new code after that.
I've not come across this issue specifically - however, if you just want the timer running while the service is running why not make it static. Then your instance context mode and instance lifetime won't affect your functionality.

WCF Proxy Client taking time to create, any cache or singleton solution for it

we have more than dozon of wcf services and being called using TCP binding. There are a lots of calls to same wcf service at various places in code.
AdminServiceClient client = FactoryS.AdminServiceClient();// it takes significant time. and
client.GetSomeThing(param1);
client.Close();
i want to cache the client or produce it from singleton. so that i can save some time, Is it possible?
Thx
Yes, this is possible. You can make the proxy object visible to the entire application, or wrap it in a singleton class for neatness (my preferred option). However, if you are going to reuse a proxy for a service, you will have to handle channel faults.
First create your singleton class / cache / global variable that holds an instance of the proxy (or proxies) that you want to reuse.
When you create the proxy, you need to subscribe to the Faulted event on the inner channel
proxyInstance.InnerChannel.Faulted += new EventHandler(ProxyFaulted);
and then put some reconnect code inside the ProxyFaulted event handler. The Faulted event will fire if the service drops, or the connection times out because it was idle. The faulted event will only fire if you have reliableSession enabled on your binding in the config file (if unspecified this defaults to enabled on the netTcpBinding).
Edit: If you don't want to keep your proxy channel open all the time, you will have to test the state of the channel before every time you use it, and recreate the proxy if it is faulted. Once the channel has faulted there is no option but to create a new one.
Edit2: The only real difference in load between keeping the channel open and closing it every time is a keep-alive packet being sent to the service and acknowledged every so often (which is what is behind your channel fault event). With 100 users I don't think this will be a problem.
The other option is to put your proxy creation inside a using block where it will be closed / disposed at the end of the block (which is considered bad practice). Closing the channel after a call may result in your application hanging because the service is not yet finished processing. In fact, even if your call to the service was async or the service contract for the method was one-way, the channel close code will block until the service is finished.
Here is a simple singleton class that should have the bare bones of what you need:
public static class SingletonProxy
{
private CupidClientServiceClient proxyInstance = null;
public CupidClientServiceClient ProxyInstance
{
get
{
if (proxyInstance == null)
{
AttemptToConnect();
}
return this.proxyInstance;
}
}
private void ProxyChannelFaulted(object sender, EventArgs e)
{
bool connected = false;
while (!connected)
{
// you may want to put timer code around this, or
// other code to limit the number of retrys if
// the connection keeps failing
AttemptToConnect();
}
}
public bool AttemptToConnect()
{
// this whole process needs to be thread safe
lock (proxyInstance)
{
try
{
if (proxyInstance != null)
{
// deregister the event handler from the old instance
proxyInstance.InnerChannel.Faulted -= new EventHandler(ProxyChannelFaulted);
}
//(re)create the instance
proxyInstance = new CupidClientServiceClient();
// always open the connection
proxyInstance.Open();
// add the event handler for the new instance
// the client faulted is needed to be inserted here (after the open)
// because we don't want the service instance to keep faulting (throwing faulted event)
// as soon as the open function call.
proxyInstance.InnerChannel.Faulted += new EventHandler(ProxyChannelFaulted);
return true;
}
catch (EndpointNotFoundException)
{
// do something here (log, show user message etc.)
return false;
}
catch (TimeoutException)
{
// do something here (log, show user message etc.)
return false;
}
}
}
}
I hope that helps :)
In my experience, creating/closing the channel on a per call basis adds very little overhead. Take a look at this Stackoverflow question. It's not a Singleton question per se, but related to your issue. Typically you don't want to leave the channel open once you're finished with it.
I would encourage you to use a reusable ChannelFactory implementation if you're not already and see if you still are having performance problems.

Importing a WCF method into WP7 App becomes async and doesnt return the list.

I am new to creating WCF projects as well as windows phone 7.
I created a simple method in WCF which just returns a list of an object.
public List<Sticky> GetSticky()
{
return stickys;
}
I then used it very simply
Sticky[] test = client.GetSticky();
When I import the WCF dll via a service reference into a console app the method acts how it should. When I import the method into a Windows Phone 7 application it become an async method (not sure what this means)and doesnt return a list, it comes up void.
client.GetStickyAsync();
If anyone can help explain what is going on and help me to be a little less confused.
Silverlight wants you to avoid making blocking service calls on the UI thread, so it forces you to use the non-blocking, async version of WCF method calls. This means that the call returns immediately and you must get the result of the call with the related event. What you need to do is register an event handler before you make the call.
client.GetStickyCompleted
+= new EventHandler<ServiceClient.GetStickyCompletedEventArgs>(client_GetStickyCompleted);
client.GetStickyAsync();
The result of your method call is one of the parameters passed into the event handler, like such
void client_GetStickyCompleted(object sender, ServiceClient.GetStickyCompletedEventArgs e)
{
List<Sticky> retList = e.Result;
}