I have a WCF web service that accesses a WCF windows service on a different machine. The windows service does all the data accessing and passes the results to the web service. I have read several articles about disposing the service client for a WCF service correctly, but I'm not sure what the best way is to do this in a web service. (If this helps, the web service is PerCall not PerSession)
This is all I'm doing right now:
Public Class Service1
Implements IService1
Private p_oWindowsService As DataService.Service1Client
Public Sub New()
p_oWindowsService = New DataService.Service1Client
End Sub
Public Function GetData(ByVal value As Integer) As String Implements IService1.GetData
Return p_oWindowsService.GetData(value)
End Function
Public Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType Implements IService1.GetDataUsingDataContract
If composite Is Nothing Then
Throw New ArgumentNullException("composite")
End If
If composite.BoolValue Then
composite.StringValue &= "Suffix"
End If
Return composite
End Function
I'm not disposing the service client at all right now, from what I've read this is a major issue. The workaround I'm looking at is something like this inside the GetData function:
Public Function GetData(ByVal value As Integer) As String Implements IService1.GetData
Using oWindowsService As New DataService.Service1Client
Return oWindowsService.GetData(value)
End Using
End Function
Based off What is the best workaround for the WCF client `using` block issue?, I know I shouldn't actually depend on the using block. But should I be creating and disposing a service client in every function? That's my real question.
Thank you.
Yes do not use dispose. Do it like this:
var client = new ...;
try {
// Do work
// Everything went well so close the client
client.Close();
}
catch( Exception ex ) {
// Something went wrong so call abort
client.Abort();
// Other logging code
}
if( client.State != System.ServiceModel.CommunicationState.Closed ) {
client.Close();
}
Calling Close() on client notifies the service instance that it is no longer in use and may be collected by GC (subject to service instance management).
You may wonder why Abort in the catch block? The reason is:
Given the WCF binding use transport sessions, the client after a fault would not even be able to close it (if there was no transport layer session then the client could use or close the proxy, but this is not recommended as the configuration of sessions could change). So after a fault has happened the only safe operation is to abort a proxy.
See this for more on Abort vs Close.
EDIT
In your comments you asked:
Do you recommend creating and closing a service client like this within every function the web service calls the windows service?
No I don't think that is necessary. Let's see you are calling the WCF service from a web application (ASP MVC), then you would do something like this in the Dispose method of the controller since ClientBase<TChannel> implements ICommunicationObject:
protected override void Dispose(bool disposing) {
base.Dispose( disposing );
ServiceHelper.DisposeService( ( this._whateverServiceClient as ICommunicationObject ) );
}
And here is the ServiceHelper class that you can use from anywhere:
public static class ServiceHelper {
/// <summary>
/// Disposes the given service.
/// </summary>
/// <param name="service">The service.</param>
public static void DisposeService(ICommunicationObject service) {
if( service != null ) {
bool abort = true;
try {
if( service.State == CommunicationState.Opened || service.State == CommunicationState.Opening ) {
service.Close();
abort = false;
}
}
finally {
// Determine if we need to Abort the communication object.
if( abort )
service.Abort();
}
}
}
}
The idea would be the same if you were calling it from another client.
You don't need to explicitly dispose the client, how ever if you truly must, this is one way of properly closing & disposing your client:
// use client
try
{
((IClientChannel)client).Close();
}
catch
{
((IClientChannel)client).Abort();
}
finally
{
((IDisposable)client).Dispose();
}
Related
I have written a windows service but when I try to stop the service it says that the service cannot be stopped at this time. Here's my whole class:
public partial class RenewalsService : ServiceBase
{
private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;
public RenewalsService()
{
InitializeComponent();
this.CanStop = true;
}
protected override void OnStart(string[] args)
{
_thread = new Thread(WorkerThread)
{
Name = "Renewals Service Thread",
IsBackground = true
};
_thread.Start();
}
protected override void OnStop()
{
try
{
if (!_shutdownEvent.SafeWaitHandle.IsClosed)
{
_shutdownEvent.Set();
}
if (_thread.IsAlive)
{
if (!_thread.Join(3000))
{
// give the thread 3 seconds to stop
_thread.Abort();
}
}
}
catch (Exception ex)
{
// _thread.Join may raise an error at this point. If it does we dont care. We dont care about any other exceptions
// since we are already in the process of closing the service.
}
finally
{
IError logger = new Logger();
Exception ex = new Exception("The Renewals service has been stopped.");
logger.Log(this, SeverityEnum.Warning, ex);
Environment.ExitCode = 0;
Environment.Exit(Environment.ExitCode);
}
}
private void WorkerThread()
{
try
{
while (!_shutdownEvent.WaitOne(1))
{
string timeToRun = ConfigurationManager.AppSettings["RunTime"];
string[] timeStrings = timeToRun.Split(':');
TimeSpan runtime = new TimeSpan(0, Int32.Parse(timeStrings[0]), Int32.Parse(timeStrings[1]), Int32.Parse(timeStrings[2]));
if (DateTime.Today.TimeOfDay.Hours == runtime.Hours &&
DateTime.Today.TimeOfDay.Minutes == runtime.Minutes)
{
Renewals renewals = new Renewals();
renewals.GenerateRenewal();
}
}
}
catch (Exception ex)
{
IError logger = new Logger();
logger.Log(this, SeverityEnum.Warning, ex);
this.OnStop();
}
}
}
What's missing to ensure the user can stop the service.
Your code looks ok to me, so here's a couple of things to check.
First, does the GenerateRenewal() method take a long time to complete? If so, you might need to periodically check _shutdownEvent inside that method for a timely shutdown. Of course, you've marked the thread as a background thread so it should shut down when you tell the service to stop anyway. I haven't seen background threads hold up process termination, but I guess there's always that chance.
Second, the more likely culprit to me is that the service has already shut down due to an exception. The Services console doesn't automatically refresh when a service shuts down, so it's possible you see the Stop link available to you when it shouldn't be. If you hit F5, the console will refresh, and if your service has stopped, the Start link should be the only one available. Check your log files to see if your exception handlers have been triggered.
UPDATE
So it looks like your WorkerThread() method is throwing an exception, which causes the service to stop. This explains why the Stop link is giving you the error message when you click it.
Providing you have sufficient permissions on your box, use this link to debug your service to find out why the exception is occurring.
HTH
The base ServiceBase class calls your overridden virtual method OnStop() when the Windows Service Control Manager ("the SCM") has sent the service a "Stop" command. In the method's implementation you are supposed to do whatever is necessary to get your service to a stopped state, then return from the method back to the ServiceBase class, which handles the interaction with the SCM, in this case to tell the SCM that your service is now stopped. The SCM will decide when your service process should be terminated, and the ServiceBase class handles that without you needing to do anything explicit.
For a well-behaved service, you should either just return at the end of your OnStop method, or throw an exception. The ServiceBase class will handle things appropriately, including logging your exception, if you have thrown one, as an error in the Windows Event Log. If your method may take a while to get your service stopped, you should call base.RequestAdditionalTime() at the appropriate points, so the base class can tell the SCM that you haven't just hung, your service is in the process of stopping.
I think your main problem lies in these lines:
Environment.ExitCode = 0;
Environment.Exit(Environment.ExitCode);
You never return to the base class at all... so the ServiceBase class never has a chance to respond gracefully to the SCM... you are just unilaterally terminating the process hosting your service. This is not what a well-behaved Windows service does.
The ServiceBase class is designed to be able to support multiple services hosted in a single service process. Individual services should not concern themselves with the lifetime of the host service process, only with the logical state of their own service.
I have two self hosted services running on the same network. The first is sampling an excel sheet (or other sources, but for the moment this is the one I'm using to test) and sending updates to a subscribed client.
The second connects as a client to instances of the first client, optionally evaluates some formula on these inputs and the broadcasts the originals or the results as updates to a subscribed client in the same manner as the first. All of this is happening over a tcp binding.
My problem is occuring when the second service attempts to subscribe to two of the first service's feeds at once, as it would do if a new calculation is using two or more for the first time. I keep getting TimeoutExceptions which appear to be occuring when the second feed is subscribed to. I put a breakpoint in the called method on the first server and stepping through it, it is able to fully complete and return true back up the call stack, which indicates that the problem might be some annoying intricacy of WCF
The first service is running on port 8081 and this is the method that gets called:
public virtual bool Subscribe(int fid)
{
try
{
if (fid > -1 && _fieldNames.LeftContains(fid))
{
String sessionID = OperationContext.Current.SessionId;
Action<Object, IUpdate> toSub = MakeSend(OperationContext.Current.GetCallbackChannel<ISubClient>(), sessionID);//Make a callback to the client's callback method to send the updates
if (!_callbackList.ContainsKey(fid))
_callbackList.Add(fid, new Dictionary<String, Action<Object, IUpdate>>());
_callbackList[fid][sessionID] = toSub;//add the callback method to the list of callback methods to call when this feed is updated
String field = GetItem(fid);//get the current stored value of that field
CheckChanged(fid, field);//add or update field, usually returns a bool if the value has changed but also updates the last value reference, used here to ensure there is a value to send
FireOne(toSub, this, MakeUpdate(fid, field));//sends an update so the subscribing service will have a first value
return true;
}
return false;
}
catch (Exception e)
{
Log(e);//report any errors before returning a failure
return false;
}
}
The second service is running on port 8082 and is failing in this method:
public int AddCalculation(string name, string input)
{
try
{
Calculation calc;
try
{
calc = new Calculation(_fieldNames, input, name);//Perform slow creation before locking - better wasted one thread than several blocked ones
}
catch (FormatException e)
{
throw Fault.MakeCalculationFault(e.Message);
}
lock (_calculations)
{
int id = nextID();
foreach (int fid in calc.Dependencies)
{
if (!_calculations.ContainsKey(fid))
{
lock (_fieldTracker)
{
DataRow row = _fieldTracker.Rows.Find(fid);
int uses = (int)(row[Uses]) + 1;//update uses of that feed
try
{
if (uses == 1){//if this is the first use of this field
SubServiceClient service = _services[(int)row[ServiceID]];//get the stored connection (as client) to that service
service.Subscribe((int)row[ServiceField]);//Failing here, but only on second call and not if subscribed to each seperately
}
}
catch (TimeoutException e)
{
Log(e);
throw Fault.MakeOperationFault(FaultType.NoItemFound, "Service could not be found");//can't be caught, if this timed out then outer connection timed out
}
_fieldTracker.Rows.Find(fid)[Uses] = uses;
}
}
}
return id;
}
}
catch (FormatException f)
{
Log(f.Message);
throw Fault.MakeOperationFault(FaultType.InvalidInput, f.Message);
}
}
The ports these are on could change but are never shared. The tcp binding used is set up in code with these settings:
_tcpbinding = new NetTcpBinding();
_tcpbinding.PortSharingEnabled = false;
_tcpbinding.Security.Mode = SecurityMode.None;
This is in a common library to ensure they both have the same set up, which is also a reason why it is declared in code.
I have already tried altering the Service Throttling Behavior for more concurrent calls but that didn't work. It's commented out for now since it didn't work but for reference here's what I tried:
ServiceThrottlingBehavior stb = new ServiceThrottlingBehavior
{
MaxConcurrentCalls = 400,
MaxConcurrentSessions = 400,
MaxConcurrentInstances = 400
};
host.Description.Behaviors.RemoveAll<ServiceThrottlingBehavior>();
host.Description.Behaviors.Add(stb);
Has anyone had similar issues of methods working correctly but still timing out when sending back to the caller?
This was a difficult problem and from everything I could tell, it is an intricacy of WCF. It cannot handle one connection being reused very quickly in a loop.
It seems to lock up the socket connection, though trying to add GC.Collect() didn't free up whatever resources it was contesting.
In the end the only way I found to work was to create another connection to the same endpoint for each concurrent request and perform them on separate threads. Might not be the cleanest way but it was all that worked.
Something that might come in handy is that I used the svc trace viewer to monitor the WCF calls to try and track the problem, I found out how to use it from this article: http://www.codeproject.com/Articles/17258/Debugging-WCF-Apps
I'm new in WCF, just learning it so far. But I was wondering how to close a WCF client connection from the client side (if it is needed at all? I think so).
I have an interface called
[ServiceContract]
ICalculatorService { blabla... }
The question is on the client side.
So far, I used the following format:
EndpointAddress epAddress = new EndpointAddress("http://localhost:8090/CalculatorService");
ICalculatorService calculatorProxy = ChannelFactory<ICalculatorService>.CreateChannel(new WSHttpBinding(), epAddress);
and now I can:
Result numeralResult = calculatorProxy.AddNumbers(4, 5);
and I got the result and I was happy.
Every single (for example) Button pressing caused the mentioned code to run once.
My question is: is the efficient?
Now I'm thinking of putting this into a separate class, for example:
class CalculatorProxy
{
static EndpointAddress epAddress = new EndpointAddress("http://localhost:8090/CalculatorService");
public static ChannelFactory<ICalculatorService> GetCalculatorProxy()
{
}
public void Dispose() { ... }
}
... and use it like:
using (ICalculatorService calculatorClient = CalculatorProxy.GetCalculatorProxy())
{
calculatorClient.AddNumbers(4, 4);
}
which one would be more efficient?
UPDATE:
Thank you all for your answers.
I finally ended up with this class:
class CalculatorServiceClient : ClientBase<ICalculatorService>, IDisposable
{
static EndpointAddress epAddress = new EndpointAddress("http://localhost:8090/CalculatorService");
ICalculatorService myCalculatorProxy;
public CalculatorServiceClient()
: base(new WSHttpBinding(), epAddress)
{
myCalculatorProxy = ChannelFactory.CreateChannel();
}
public static CalculatorServiceClient GetNewInstance()
{
return new CalculatorServiceClient();
}
public Result AddNumbers(int aIn, int bIn)
{
return myCalculatorProxy.AddNumbers(aIn, bIn);
}
public void Dispose()
{
try
{
Close();
}
catch (CommunicationObjectFaultedException ex)
{
throw new DBCommunicationException("CalculatorServiceClient is in the Faulted state.", ex);
}
catch (Exception ex)
{
throw new DBCommunicationException("Communication is unsuccessful between the CalculatorServiceClient and the CalculatorService.", ex);
}
}
}
And use it in this way:
try
{
using (CalculatorServiceClient calculatorClient = CalculatorServiceClient.GetNewInstance())
{
Result aResult = calculatorClient.AddNUmbers(tbA.Text, tbB.Text);
}
}
catch (DBCommunicationException ex)
{
MessageBox.Show("Service is shut down.");
}
My question is: is this efficient?
You should just close the client when each operation you have done is completed and you don't need anymore to make other calls.
When your work is finished, just close the client using the Close method:
calculatorProxy.Close();
About the Close() method, the MSDN documentation states:
This method causes a CommunicationObject to gracefully transition from
any state, other than the Closed state, into the Closed state. The
Close method allows any unfinished work to be completed before
returning. For example, finish sending any buffered messages.
About your approach, I think the second one is fine and more efficient, because you're also implementing the Dispose pattern and release the used resources (this depends on the resources you're using). Just add the Close() method when the work is finished:
calculatorClient.AddNumbers(4, 4);
calculatorProxy.Close();
Remember also that there's no performance issue creating and closing continuously the WCF clients. This is just a normal habitude.
using (var client = new CalculatorServiceClient())
{
client.SomeMethod();
}
The CalculatorServiceClient object will be available once you add a Service Reference to your Calculator WebService to your client project.
you can call the close method of your proxy class.
like
calculatorProxy.Close();
Alternatively you call the abort method on your service proxy class in case of exception.
try
{
calculatorProxy.SomeMethod();
calculatorProxy.Close();
}
catch
{
calculatorProxy.Abort();
}
Refer to this link for further details
I think you would find it better to put all of that in a class. Establishing an instance of the class can construct the connection and close/dispose when the time comes. Until then, you have an open and active channel to make calls to.
what's the problem with the following code...
I have this Complex class:
public class Complex : MarshalByRefObject
{
public double imaginary{get;set;}
public double real{get;set;}
public void setReal(double re)
{
real = re;
}
public void setImaginary(double im)
{
imaginary = im;
}
public Complex(double im, double re)
{
imaginary = im;
real = re;
}
public void writeMembers()
{
Console.WriteLine(real.ToString() + imaginary.ToString());
}
}
Actually, there's a little more to it, but the code it's too big, and we don't use the rest of it in the context of this.
Then, I implemented a server which listens for connections:
HttpChannel channel = new HttpChannel(12345);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(SharedLib.Complex), "ComplexURI", WellKnownObjectMode.SingleCall);
Console.WriteLine("Server started. Press any key to close...");
Console.ReadKey();
foreach (IChannel ichannel in ChannelServices.RegisteredChannels)
{
(ichannel as HttpChannel).StopListening(null);
ChannelServices.UnregisterChannel(ichannel);
}
Then, we have the client:
try
{
HttpChannel channel = new HttpChannel();
RemotingConfiguration.Configure("Client.exe.config", false);
Complex c1 = (Complex)Activator.GetObject(typeof(Complex), "http://localhost:12345/ComplexURI");
if (RemotingServices.IsTransparentProxy(c1))
{
c1.real = 4;
c1.imaginary = 5;
c1.writeMembers();
Console.ReadLine();
}
else
{
Console.WriteLine("The proxy is not transparent");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
Then, I run the server, which opens a console window, and I run the client.
Instead of displaying 4 and 5 on the server window, I merely get 00, a sign that the members weren't changed.
How do I do, so the members change?
Thanks.
The problem is that you're using WellKnownObjectMode.SingleCall. As the documentation says:
SingleCall Every incoming message is serviced by a new object instance.
Singleton Every incoming message is serviced by the same object instance.
See also the documentation for RegisterWellKnownServiceType:
When the call arrives at the server, the .NET Framework extracts the URI from the message, examines the remoting tables to locate the reference for the object that matches the URI, and then instantiates the object if necessary, forwarding the method call to the object. If the object is registered as SingleCall, it is destroyed after the method call is completed. A new instance of the object is created for each method called.
In your case, the statement c.Real = 4 is a call to the Real property setter. It makes a call to the remote object, which creates a new object, sets the Real property to 4, and returns. Then when you set the imaginary property, it creates a new object, etc.
If you want this to work, you'll have to use WellKnownObjectMode.Singleton. But you might want to ask yourself if you really want such a "chatty" interface. Every time you set a property, it requires a call through the proxy to the server.
And, finally, you might consider abandoning Remoting altogether. It's old technology, and has a number of shortcomings. If this is new development, you should be using Windows Communications Foundation (WCF). The Remoting documentation says:
This topic is specific to a legacy technology that is retained for backward compatibility with existing applications and is not recommended for new development. Distributed applications should now be developed using the Windows Communication Foundation (WCF).
I have 2 WCF services that are both installed locally on the same Windows Service. The 2 WCF services make calls to the same database and use Net TCP Binding.
Side Note: I made 2 services instead of 1 because the service had too many methods and as a result, the XML file was too large and I couldn't add the service reference to the consumer app. Also, it's more readable this way.
On the client app, I've added a service reference to both WCF services. To use the services, I extended the CommunicationObject so it has a "Using()" method: see the code below.
Communication Object Extension for .Using() Method
public static class CommunicationObjectExtensions
{
public static void Using<T>(this T client, Action<T> work)
where T : ICommunicationObject
{
try
{
// make sure client is open
//client.Open(); // didn't work
work(client);
}
catch (CommunicationException e)
{
client.Abort();
throw;
}
catch (TimeoutException e)
{
client.Abort();
throw;
}
catch (Exception e)
{
client.Abort();
throw;
}
finally
{
client.Close();
}
}
}
Service Calls
new ServiceClientA().Using(client =>
{
var someObjectA = client.GetSomeObjectA();
});
new ServiceClientB().Using(client =>
{
var someObjectB = client.GetSomeObjectB();
});
I get the "The socket connection has been disposed" error when ServiceClientB's method actually has data to return (versus an empty list) and returns (I'm able to debug and go through the entire service call).
I don't run into this problem when using the other WCF services that point to different databases.
Anyone have any ideas what's going on?
Update
Ok turns out it only happens with the method I'm calling (client.GetSomeObjectB()). The object it's returning is causing errors. Apparently this is because the object is too big, but it shouldn't be a problem (since I'm only returning 1 small object).