We will break the problem in small sets as this will answer few commonly asked questions like – Self hosting a WCF, Hosting WCF in desktop application, Inter- Process communication using WCF.
We will use the application we created in last post. Please find below the project structure that we will be using.
We are using a “common” project to define the contract so that contracts can be shared between projects.
Contract
using System.ServiceModel;
namespace Common
{
[ServiceContract]
public interface ICommunicate
{
[OperationContract]
string HandShake(string message);
}
}
Add reference of “Common” project to the main (windows application project - BackgroundApp).
Service Class
using Common;
namespace BackgroundApp.Service
{
public class Communicate : ICommunicate
{
public string HandShake(string message)
{
return "Reply - " + (string.IsNullOrEmpty(message) ? "You sent blank" : message);
}
}
}
Class to start different instance of service on different thread
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Threading;
using BackgroundApp.Service;
namespace BackgroundApp
{
public class ThreadedService
{
const int SleepTime = 100;
private ServiceHost _serviceHost = null;
private readonly Thread _thread;
private bool _keepRunning;
public ThreadedService()
{
_thread = new Thread(new ThreadStart(StartServer));
_thread.Start();
}
private void StartServer()
{
try
{
_keepRunning = true;
//not using "using" as host needs to be present for client to access it and client gets activated latter in the flow.
_serviceHost = new ServiceHost(typeof(Communicate),
new Uri[]
{
new Uri("http://localhost:8000/CommunicationService")
});
// Enable metadata publishing.
var serviceMetadataBehavior = new ServiceMetadataBehavior
{
HttpGetEnabled = true,
MetadataExporter = {PolicyVersion = PolicyVersion.Policy15}
};
_serviceHost.Description.Behaviors.Add(serviceMetadataBehavior);
// Start the host
_serviceHost.Open();
//keep the thread running
while (_keepRunning)
{
// Wait until thread is stopped
Thread.Sleep(SleepTime);
}
_serviceHost.Close();
}
catch (Exception ex)
{
if (_serviceHost != null)
{
_serviceHost.Close();
}
}
}
/// <summary>
/// Request the end of the thread method.
/// </summary>
public void StopServer()
{
lock (this)
{
_keepRunning = false;
}
}
}
}
Class to maintain current instance of service
namespace BackgroundApp
{
public class ServiceInstance
{
private static volatile ServiceInstance _instance;
private static readonly object SyncRoot = new object();
#region Constructor
private ServiceInstance()
{
}
#endregion
#region static properties
public static ServiceInstance Instance
{
get
{
if(_instance == null)
{
lock (SyncRoot)
{
if(_instance == null)
{
_instance = new ServiceInstance();
}
}
}
return _instance;
}
}
#endregion
public ThreadedService CurrentServerInstance { get; set; }
}
}
Program start point – Desktop App
using System;
using System.Drawing;
using System.Windows.Forms;
using BackgroundApp.Properties;
namespace BackgroundApp
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ApplicationStartUp());
}
}
public class ApplicationStartUp : Form
{
private NotifyIcon trayIcon;
private ContextMenu trayMenu;
private void InitializeComponent()
{
trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("Exit", OnExit);
trayIcon = new NotifyIcon();
trayIcon.Text = Resources.TrayIcon;
trayIcon.Icon = new Icon(global::BackgroundApp.Properties.Resources.IntegratedServer, 40, 40);
trayIcon.ContextMenu = trayMenu;
trayIcon.Visible = true;
}
//Ctor
public ApplicationStartUp()
{
InitializeComponent();
ThreadedService threadedService = new ThreadedService();
ServiceInstance.Instance.CurrentServerInstance = threadedService;
}
protected override void OnLoad(EventArgs e)
{
Visible = false;
ShowInTaskbar = false;
base.OnLoad(e);
}
private void OnExit(object sender, EventArgs e)
{
ServiceInstance.Instance.CurrentServerInstance.StopServer();
// Release the icon resource.
trayIcon.Dispose();
Application.Exit();
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
// Release the icon resource.
trayIcon.Dispose();
}
base.Dispose(isDisposing);
}
}
}
Comments
Post a Comment