简体   繁体   中英

Restart a WCF service hosted by a C# console application

I have a WCF service that is hosted on ac# console application. Is there a way to restart this service, preferably by calling an endpoint in the service itself (ex. myService.Restart()).

Thanks

I have to do something similar when I perform an automatic update of a remote WCF service. In your Restart() method, close the host:

    try
    {
        host.Description.Endpoints.Where(x => !x.Address.ToString().EndsWith("MEX")).ForEach(endpoint => _log.InfoFormat("Closing {0}", endpoint.Address));
        host.Close(TimeSpan.FromSeconds(5));
    }
    catch (Exception)
    {
        host.Abort();
    }

I wait for my update to apply, and then after a success or failure, I re-open the host using the same code I used to start it in the first place.

If you just wanted to restart immediately, you could just call host.Open(), or you could set up a timer to call it, etc.

try
{
    host.Open();
    host.Description.Endpoints.Where(x => !x.Address.ToString().EndsWith("MEX")).ForEach(endpoint => _log.InfoFormat("Host opened at: {0}", endpoint.Address));
}
catch (Exception ex)
{
    _log.Error("Unable to open host.", ex);
}

To answer my question, I have solved the problem by doing the following:

  • Separating the code that loads the DLL files from the WCF service code into another class library project
  • Create an interface with the same method signatures as the ones that load DLL files in the new project (this interface is used by both projects now)
  • In the web service, load the other project in a new application domain. This way the DLL files are locked by the new application domain not the default.

If I want to update my nunit DLL files now, all I have to do is unload the application domain from the web service, update the files and finally create a new application domain.

AppDomain remoteDomain = AppDomain.CreateDomain("New Domain");
IClass1 class1 = (IClass1)remoteDomain.CreateInstanceFromAndUnwrap(
                           "Test1.dll", "Test1.Class1");

Note: IClass1 is the common interface between the projects.

you definitely are not going to be able to 'restart' a faulted service from calling that same service itself. In theory you could host 2 services in the same process. put the one you want to be 'restartable' in a public static variable and restart it within the other service. The problem would be restarting the restarter service if it faults... :) and you definitely want 'administrator-like' restrictions on your restarter service so unauthorized users can't do it.

It's a bit kludgy, but I suppose you could expose a callback on your service that the host could attach to and take appropriate action when it's triggered. That would give your host the ability to decide what a "restart" really means and how it needs to be executed. More importantly, it lets your decide whether it should do something extreme like spawn off a watcher process and then off itself or gracefully trash and reinstantiate your service (preferable).

Mmmmmm... kludge....

You cannot ask a service to restart itself. Consider a windows service (a service hosted in windows provided container) which has a RESTART functionality. Here RESTART functionality is provided not by the service but by the container. The container controls how to stop the service and start it.

Similarly in your case, you should try to look out for options if your container can provide the functionality you need. Since you want to control it remotely, the container should also be available remotely, which cannot be possible if the container is a console application. Instead it has to be another web service or web application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM