WCF client reconnect automatically - c#

I have a wcf service, and the corresponding client. When service faulted every call from client to service throw a exception. But i need that client reconnect, so i wrap a client into exception handler with reconnection.
What is a prefer way to implement auto reconnect behavior?
My client:
internal sealed class BloombergClient
{
#region Singleton
private static Lazy<BloombergClient> instance = new Lazy<BloombergClient>(() => new BloombergClient(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
public static BloombergClient Instance { get { return instance.Value; } }
#endregion
private readonly ExceptionReconnectHandler exceptionHandler;
private readonly Object lockObject = new Object();
private readonly ManualResetEventSlim eventSlim = new ManualResetEventSlim(true);
private BloombergModuleServiceClient client;
private volatile Boolean isConnecting;
public event System.EventHandler ConnectionEstablished;
private BloombergClient()
{
this.exceptionHandler = new ExceptionReconnectHandler(HandleException);
Connect();
}
//Example method
public Double GetDailyClose(String bloombergTicker, DateTime date)
{
eventSlim.Wait();
return exceptionHandler.Execute(() => this.client.GetDailyClose(bloombergTicker, date));
}
private void HandleException(Exception e)
{
Connect();
}
private void BloombergServiceClientFaulted(object sender, EventArgs e)
{
Connect();
}
private Boolean CreateClient()
{
Boolean init = false;
if (this.client != null)
{
((ICommunicationObject)client).Faulted -= BloombergServiceClientFaulted;
((ICommunicationObject)client).Closed -= BloombergServiceClientFaulted;
}
this.client = new BloombergModuleServiceClient();
if (this.client.State == CommunicationState.Created)
{
((ICommunicationObject)client).Faulted += BloombergServiceClientFaulted;
((ICommunicationObject)client).Closed += BloombergServiceClientFaulted;
init = true;
}
else
{
init = false;
}
return init;
}
private void Connect()
{
lock (this.lockObject)
{
if (isConnecting) return;
lock (this.lockObject)
{
if (isConnecting) return;
isConnecting = true;
}
}
//if (eventSlim.IsSet) return; - offcourse not working
eventSlim.Reset();
try
{
while (true)
{
try
{
if (client != null && client.State == CommunicationState.Opened)
{
((ICommunicationObject)client).Abort();
}
if (CreateClient())
{
break;
}
}
catch (Exception e)
{
Log.Instance.WriteLineT(e.Message, "Bloomberg Client");
}
Thread.Sleep(1000);
}
}
finally
{
eventSlim.Set();
isConnecting = false;
ConnectionEstablished.Raise(this);
}
}
}
public class ExceptionReconnectHandler
{
private readonly Action<Exception> handler;
public ExceptionReconnectHandler(Action<Exception> handler)
{
if (handler == null) throw new ArgumentNullException("handler");
this.handler = handler;
}
public virtual T Execute<T>(Func<T> func)
{
if (func == null) throw new ArgumentNullException("func");
while (true)
{
try
{
return func();
}
catch (Exception e)
{
handler(e);
}
}
}
public virtual void Execute(Action action)
{
if (action == null) throw new ArgumentNullException("action");
while (true)
{
try
{
action();
return;
}
catch (Exception e)
{
handler(e);
}
}
}
}

Related

WCF Web Socket Service - lock not working correctly

In my web socket wcf service I'm using timer elapsed event to do some logic on my object and after that send information to client (by callback object). I also track callback closed event to clean all object that I'm using in timer elapsed event handler. The problem that i occured is that, when I'm trying to dispose my object i get errors that is still working and to prevent that i try to use lock in both code (timer elapsed event and closed channel event) but it not working correctly (i'm still getting errors that i'm calling method on my object that is no allowed for this moment - this mean that timer elapsed and also call it in the same time).
Is WCF do something special which causes to lock don't work as I expected ?
Here is some of my code:
[ServiceContract(CallbackContract = typeof(IWebSocketsCallback))]
public interface IWebSockets
{
[OperationContract(IsOneWay = true, Action = "*")]
void Start(Message msg);
}
[ServiceContract]
public interface IWebSocketsCallback
{
[OperationContract(IsOneWay = true, Action = "*")]
void SendToClient(Message msg);
}
public class WebSockets : IWebSockets
{
private IWebSocketsCallback callback;
private bool handlePIChanges = false;
private PIDataPipe pipe;
private PIEventsProducer piEventsProducer;
private Timer timer;
private readonly object timerLock = new object();
private readonly object pipeLock = new object();
private bool isPipeClosed = false;
public WebSockets()
{
callback = OperationContext.Current.GetCallbackChannel<IWebSocketsCallback>();
((IChannel)callback).Closed += WebSockets_Closed;
}
public void Start(Message msg)
{
// some custom logic that i ommited ...
timer = CreateTimer();
timer.Elapsed += (sender, e) => PIQueryingCallback(pipe, timer);
}
private void WebSockets_Closed(object sender, EventArgs e)
{
lock (timerLock)
{
handlePIChanges = false;
if (timer != null)
{
timer.Stop();
timer.Dispose();
piEventsProducer.Clear();
}
}
lock (pipeLock)
{
if (pipe != null)
{
pipe.RemoveSignups(pipe.AsReadOnly()); // this cause error, because GetObserverEvents not stopped working
pipe.Close();
isPipeClosed = true;
}
}
}
private void PIQueryingCallback(PIDataPipe pipe, Timer myTimer)
{
bool moreIndicator;
AFErrors<PIPoint> errors;
lock (pipeLock)
{
do
{
if (handlePIChanges && !isPipeClosed)
{
try
{
errors = pipe.GetObserverEvents(2000, out moreIndicator); // this method calls make block for other call on this object untill it return results
}
catch (Exception e)
{
moreIndicator = false;
continue;
}
}
else
{
moreIndicator = false;
}
}
while (moreIndicator);
}
if (handlePIChanges)
{
lock (timerLock)
{
if (handlePIChanges)
{
myTimer.Start();
}
}
}
}
// this method is called after GetObserveEventsCompleted
private void HandlePIDataEventProducerChanges(string msg)
{
if (handlePIChanges && !isPipeClosed)
{
if (((IChannel)callback).State == CommunicationState.Opened)
{
try
{
callback?.SendPIDataChangesToClient(CreateMessage(msg));
}
catch (Exception ex)
{
}
}
}
}
}

Is there an advantage/disadvantage to open a different tcp port for every client?

I build a middle ware server.
I have 5(or 6) clients(different computer/IP address), and every client can have up to 6 connection -> max 36 connection to the server.
It is better to use only 1 port for all (e.g. 9000) or one different port for every client(e.g. 9000-9005) ?
I write me a simple test server(see code).
It worked like expected but maybe there is some room for optimization.
Thanks
My TCP server
public class TCPServerMulti : IDisposable
{
private static TcpListener _tcpListener;
private string _ipAdress = "";
private int _port = 9050;
private readonly Thread _listener;
private readonly bool _running;
private int cc = 0; //Test Counter
public string IPAdress
{
get { return _ipAdress; }
set { _ipAdress = value; }
}
public TCPServerMulti(int port)
{
if(port>0)
_port = port;
_running = true;
string sHostName = Dns.GetHostName();
IPAdress = "";
//Only use the first address -> need to change
IPAddress[] localAddress = Dns.GetHostAddresses(sHostName);
foreach (IPAddress ipAddress in localAddress)
{
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
_tcpListener = new TcpListener(ipAddress, _port);
IPAdress = ipAddress.ToString();
break;
}
}
if (IPAdress == "")
{
Console.Writeline("TCP Error");
return;
}
_tcpListener.Start();
_listener = new Thread(Listen) { IsBackground = true };
_listener.Start();
}
public TCPServerMulti():this(-1)
{}
//listening for clients
public void Listen()
{
try
{
while(_running)
{
cc++;
//create a own client object for every connection
TCPClientData cd = new TCPClientData(this, ""+cc, _tcpListener.AcceptTcpClient());
cd.StartClient();
if (ClientConnected != null) ClientConnected("Connected: " + cc);
}
_tcpListener.Stop();
}
catch (Exception)
{
}
}
public void Dispose()
{
_listener.Abort();
_tcpListener.Stop();
}
//Handle for Mainthread
internal void ReceiveClient(TCPClientData sender, string msg)
{
if (ReceiveMsg != null)
ReceiveMsg(sender, msg);
}
public delegate void ReceiveEventHandler(TCPClientData sender, string msg);
public event ReceiveEventHandler ReceiveMsg;
public delegate void ConnectedEventHandler(string msg);
public event ConnectedEventHandler ClientConnected;
}
Clientdata object
public class TCPClientData : IDisposable
{
private TCPServerMulti _master;
private byte[] _data;
private NetworkStream _networkStream;
private int _received;
private TcpClient _tcpClient;
private Thread _worker;
private bool _wrunning;
private string _id;
public TCPClientData(TCPServerMulti master,string id,TcpClient client)
{
_data = new byte[1024];
_master = master;
_id = id;
_tcpClient = client;
}
public string ID
{
get { return _id; }
}
private string ByteArrayToString(byte[] arr)
{
UTF8Encoding enc = new UTF8Encoding();
return enc.GetString(arr);
}
private byte[] StringToByteArray(string data)
{
UTF8Encoding enc = new UTF8Encoding();
return enc.GetBytes(data);
}
// Reading Data
private void Worker()
{
try
{
while (_wrunning)
{
if (_networkStream.DataAvailable)
{
_received = _networkStream.Read(_data, 0, _data.Length);
string s = ByteArrayToString(_data);
_master.ReceiveClient(this, s.Substring(0, _received));
}
else
{
Thread.Sleep(20);
}
}
_networkStream.Close();
_tcpClient.Close();
}
catch (Exception)
{ }
}
public void Dispose()
{
_worker.Abort();
_networkStream.Close();
_tcpClient.Close();
}
public void StartClient()
{
_networkStream = _tcpClient.GetStream();
_networkStream.ReadTimeout = 200;
_wrunning = true;
_worker = new Thread(Worker) { IsBackground = true };
_worker.Start();
}
public void StopClient()
{
_wrunning = false;
Thread.Sleep(700);
}
//Sending Data
public void WriteData(string msg)
{
byte[] b = StringToByteArray(msg);
_networkStream.Write(b,0,b.Length);
_networkStream.Flush();
}
}
Main Thread
static void Main(string[] args)
{
//Create Server
TCPServerPlugin.TCPServerMulti server=new TCPServerMulti(12345);
server.ClientConnected += Server_ClientConnected;
server.ReceiveMsg += Server_ReceiveMsg;
while (true)
{
}
}
//Callbacks
private static void Server_ClientConnected(string msg)
{
Console.WriteLine(msg);
}
private static void Server_ReceiveMsg(TCPClientData sender, string msg)
{
Console.WriteLine(string.Format("Sender: {0} -> MSG:{1}",sender.ID,msg));
if (msg == "!!X")
{
sender.Dispose();
sender = null;
}
else if(msg=="DATE")
sender.WriteData(DateTime.Now.ToLongDateString());
else if(msg=="TIME")
sender.WriteData(DateTime.Now.ToShortTimeString());
}

C# Server Socket stops accepting new connections

I’ve written TCP socket catcher based on server socket and events for transferring caught connections to high level.
public class TcpCatcher
{
private static readonly Exception IsStartedException = new Exception("Catcher has already been started.");
private int _port;
private int _openTimeout;
private Socket _serverSocket;
private SocketAsyncEventArgs _acceptAsyncArg;
public int Port
{
get => _port;
set
{
if (IsStarted)
throw IsStartedException;
_port = value;
}
}
public int OpenTimeout
{
get => _openTimeout;
set
{
if (IsStarted)
throw IsStartedException;
_openTimeout = value;
}
}
public bool IsStarted { get; protected set; }
public event Action<Socket> ConnectionCatched;
public event Action<string> Log;
public TcpCatcher()
{
_acceptAsyncArg = new SocketAsyncEventArgs();
_acceptAsyncArg.SetBuffer(null, 0, 0);
_acceptAsyncArg.Completed += OnAcceptSocket;
}
private void OnLog(string message)
{
if (Log != null)
Log(message);
}
private void AcceptSocket()
{
OnLog("AcceptSocket is executing");
bool isAsync;
do
{
isAsync = _serverSocket.AcceptAsync(_acceptAsyncArg);
if (!isAsync)
{
OnLog($"AcceptAsync finished Sync.");
if (_acceptAsyncArg.SocketError == SocketError.Success)
ConnectionCatched(_acceptAsyncArg.AcceptSocket);
}
} while (!isAsync);
OnLog("AcceptSocket finished");
}
private void OnAcceptSocket(object sender, SocketAsyncEventArgs asyncArg)
{
OnLog("Caught new socket!");
if (asyncArg.SocketError != SocketError.Success)
{
OnLog($"Socket has bad status:${asyncArg.SocketError}");
asyncArg.AcceptSocket?.Close();
}
else
{
ConnectionCatched(asyncArg.AcceptSocket);
}
OnLog($"Caught socket was processed");
asyncArg.AcceptSocket = null;
if (IsStarted)
AcceptSocket();
}
public void Start()
{
OnLog($"Starting");
IsStarted = true;
_serverSocket?.Close();
_serverSocket = new Socket(SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, Port));
_serverSocket.Listen((int)SocketOptionName.MaxConnections);
AcceptSocket();
}
public void Finish()
{
OnLog($"Stopping");
_serverSocket.Disconnect(false);
_serverSocket.Close();
_serverSocket.Dispose();
_serverSocket = null;
IsStarted = false;
}
}
Catchers are used in a Windows Service and initialized when the service is started. They work about 2-4 days and stop for unknown reasons accepting sockets one by one. Can you explain why it may be and how this problem can be solved?

Want to set the UI threads in a progressbar in C# when I import data into a database

I've got a method called Import that imports the data of an xml file into the database. It looks like this:
private void SavingXMLFile()
{
//Save the file:
if (rootElement != null)
{
try
{
using (FileStream fsHosp = new FileStream("Data/ConfigOrgHospital.xml", FileMode.Truncate, FileAccess.Write))
{
using (XmlWriter x = XmlWriter.Create(fsHosp))
{
SerializeHospitalData(x, rootElement);
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
try
{
Import("Hospitals");
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
Then it goes to the import method:
public void Import(string sourceFile)
{
IProgressReporter progressReporter = new ProgressReporter();
BackgroundThreading.RunInBackground<int>((object input) =>
{
foreach (IConfigRunner runner in Runners.OrderBy(r => r.Priority))
{
runner.DoImport(progressReporter, sourceFile);
}
return 0;
}, (answer, error, w) =>
{
if (error != null)
{
//ShowError(error);
}
else
{
//AddProgress("Export ready");
}
//DoReady();
}, (error) =>
{
//ShowError(error);
});
}
Then it does a DoImport:
public interface IConfigRunner
{
int Priority { get; }
void DoExport(IProgressReporter progress);
void DoImport(IProgressReporter progress, string filename);
}
[Export]
public void DoImport(IProgressReporter progress, string filename = null)
{
if (filename.Equals("Hospitals"))
{
if (File.Exists(HOSPITALFILE))
{
progress.AddProgress("Importing " + HOSPITALFILE);
using (OrgEntities orgEntityModel = ModelFactory.GetOrgEntities())
{
Tools.ValidateXml(HOSPITALFILE, "Xsd\\hospital.xsd");
XmlSerializer inSerializer = new XmlSerializer(typeof(HospitalRoot));
TextReader reader = new StreamReader(HOSPITALFILE);
HospitalRoot root = (HospitalRoot)inSerializer.Deserialize(reader);
reader.Close();
try
{
OrgHospitalXml.Insert(orgEntityModel, root.Hospitals);
}
catch (ImportException e)
{
progress.AddProgress(e.Message + ": " + e.Item);
throw e;
}
}
}
}
Is there any way that I can show the progression of this in a progressbar? Or how to find all the UI Threads? Thx in advance
BackgroundWorker:
public static class BackgroundThreading
{
public static BackgroundWorker RunInBackground<T>(object param, Func<object, T> call, Action<T, Exception, BackgroundWorker> callBack, Action<Exception> errorHandler = null) where T : new()
{
BackgroundWorker worker = new BackgroundWorker();
DoWorkEventHandler workHandler = null;
RunWorkerCompletedEventHandler completeHandler = null;
workHandler = delegate(object s, DoWorkEventArgs args)
{
args.Result = call(args.Argument);
args.Cancel = worker.CancellationPending;
};
completeHandler = delegate(object s, RunWorkerCompletedEventArgs args)
{
if (!args.Cancelled)
{
if (args.Error != null)
{
if (!(args.Error is FaultException))
{
T result = new T();
callBack(result, args.Error, (BackgroundWorker)s);
}
else
{
if (errorHandler == null)
{
string message;
if (args.Error.InnerException != null)
{
message = args.Error.InnerException.Message;
}
else
{
message = args.Error.Message;
}
Logger.LogError("SVC", Logger.SVC_ERROR_001, new object[1] { message });
throw args.Error;
}
else
{
errorHandler(args.Error);
}
}
}
else
{
callBack((T)args.Result, null, (BackgroundWorker)s);
}
((BackgroundWorker)s).DoWork -= workHandler;
((BackgroundWorker)s).RunWorkerCompleted -= completeHandler;
}
};
worker.DoWork += workHandler;
worker.RunWorkerCompleted += completeHandler;
worker.WorkerSupportsCancellation = true;
worker.RunWorkerAsync(param);
return worker;
}
public static BackgroundWorker RunInBackground<T>(Func<object, T> call, Action<T, Exception, BackgroundWorker> callBack, Action<Exception> errorHandler = null) where T : new()
{
return RunInBackground<T>(null, call, callBack, errorHandler);
}
Use BackgroundWorker http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
ProgressChanged event is automatically run on UI thread while your actual code runs in a different thread.
As far as i remember you need to hook up to the progress changed event and update your progress bar in this.
You then need to call worker.reportProgress(x).
Another option is to set your progress bar to marque and call Application.DoEvents every now and then but this may well be frowned upon by other members

Implementation of processing items asynchronously

Is there any good implementation of processing queue items asynchronously?
If you're using .NET 4, a lot of this comes for free out of the box.
If you've already got all the items, you can use Parallel.ForEach. If you need a producer/consumer queue, you can use BlockingCollection<T> to wrap one of the concurrent collections (such as ConcurrentQueue<T> or ConcurrentStack<T>). How you use that is up to you; there's a blog post here going into a detailed example, and there are probably other similar posts around too. (You might want to look at the Parallel Team Blog for a lot more material.)
You could take a look at a Producer/Consumer pattern if you are unfortunate enough not to be using .net 4.
Here is my code I have disassembled, my apologies for the mess but you should be able to use this by adding to a project and recompiling, then creating your process using the resulting dll.
Enum for ChannelState:
public enum ChannelState
{
WaitingForSend,
WaitingForReceive,
Open
}
Interfaces:
public interface IChannel<TMessage>
{
// Methods
TMessage Receive();
void Send(TMessage message);
// Properties
bool CanReceive { get; }
bool CanSend { get; }
ChannelState State { get; }
}
using System;
public interface IReceiver<TMessage>
{
// Events
event EventHandler<MessageReceivedEventArgs<TMessage>> MessageReceived;
// Methods
void Activate();
void Deactivate();
// Properties
bool IsActive { get; }
}
Concrete classes:
using System.Collections.Generic;
using System.Threading;
using System;
public class BufferedChannel<TMessage> : IChannel<TMessage>
{
// Fields
private int _blockedReceivers;
private int _blockedSenders;
private Queue<TMessage> _buffer;
private int _capacity;
private EventWaitHandle _capacityAvailableEvent;
private EventWaitHandle _messagesAvailableEvent;
// Methods
public BufferedChannel()
{
this._buffer = new Queue<TMessage>();
this._messagesAvailableEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
this._capacityAvailableEvent = new EventWaitHandle(true, EventResetMode.AutoReset);
this._capacity = 50;
}
public BufferedChannel(int bufferSize)
{
this._buffer = new Queue<TMessage>();
this._messagesAvailableEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
this._capacityAvailableEvent = new EventWaitHandle(true, EventResetMode.AutoReset);
this._capacity = 50;
if (bufferSize <= 0)
{
throw new ArgumentOutOfRangeException("bufferSize", bufferSize, ExceptionMessages.ChannelsBufferSizeMustBeGreaterThanZero);
}
this._capacity = bufferSize;
}
public TMessage Receive()
{
Interlocked.Increment(ref this._blockedReceivers);
try
{
this._messagesAvailableEvent.WaitOne();
}
catch
{
lock (this._buffer)
{
Interlocked.Decrement(ref this._blockedReceivers);
}
throw;
}
lock (this._buffer)
{
Interlocked.Decrement(ref this._blockedReceivers);
this._capacityAvailableEvent.Set();
if ((this._buffer.Count - 1) > this._blockedReceivers)
{
this._messagesAvailableEvent.Set();
}
return this._buffer.Dequeue();
}
}
public void Send(TMessage message)
{
Interlocked.Increment(ref this._blockedSenders);
try
{
this._capacityAvailableEvent.WaitOne();
}
catch
{
lock (this._buffer)
{
Interlocked.Decrement(ref this._blockedSenders);
}
throw;
}
lock (this._buffer)
{
Interlocked.Decrement(ref this._blockedSenders);
this._buffer.Enqueue(message);
if (this._buffer.Count < this.BufferSize)
{
this._capacityAvailableEvent.Set();
}
this._messagesAvailableEvent.Set();
}
}
// Properties
public int BufferCount
{
get
{
lock (this._buffer)
{
return this._buffer.Count;
}
}
}
public int BufferSize
{
get
{
lock (this._buffer)
{
return this._capacity;
}
}
set
{
lock (this._buffer)
{
if (value <= 0)
{
throw new ArgumentOutOfRangeException("BufferSize", value, ExceptionMessages.ChannelsBufferSizeMustBeGreaterThanZero);
}
this._capacity = value;
if ((this._blockedSenders > 0) && (this._capacity > this._buffer.Count))
{
this._capacityAvailableEvent.Set();
}
}
}
}
public bool CanReceive
{
get
{
return true;
}
}
public bool CanSend
{
get
{
return true;
}
}
public ChannelState State
{
get
{
if (this._blockedSenders > 0)
{
return ChannelState.WaitingForReceive;
}
if (this._blockedReceivers > 0)
{
return ChannelState.WaitingForSend;
}
return ChannelState.Open;
}
}
}
using System;
using System.Collections.Generic;
using System.Threading;
using System.ComponentModel;
using System.Runtime.CompilerServices;
public sealed class Receiver<TMessage> : Component, IReceiver<TMessage>
{
// Fields
private volatile bool _continue;
private object _controlLock;
private volatile bool _disposed;
private Thread _receiverThread;
private bool _receiving;
private object _receivingLock;
private object _threadLock;
[CompilerGenerated]
private IChannel<TMessage> channel;
// Events
public event EventHandler<MessageReceivedEventArgs<TMessage>> MessageReceived;
// Methods
public Receiver(IChannel<TMessage> channel)
{
this._controlLock = new object();
this._threadLock = new object();
this._receivingLock = new object();
if (channel == null)
{
throw new ArgumentNullException("channel");
}
this.Channel = channel;
}
public void Activate()
{
this.CheckDisposed();
lock (this._controlLock)
{
if (this._receiverThread != null)
{
throw new InvalidOperationException();
}
this._continue = true;
this._receiverThread = new Thread(new ThreadStart(this.RunAsync));
this._receiverThread.IsBackground = true;
this._receiverThread.Start();
}
}
private void CheckDisposed()
{
if (this._disposed)
{
throw new ObjectDisposedException(base.GetType().Name);
}
}
public void Deactivate()
{
lock (this._controlLock)
{
if (this._continue)
{
this._continue = false;
lock (this._threadLock)
{
if (this._receiverThread != null)
{
this.SafeInterrupt();
this._receiverThread.Join();
this._receiverThread = null;
}
}
}
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
this.Deactivate();
this._disposed = true;
}
}
private void OnMessageReceived(TMessage message)
{
EventHandler<MessageReceivedEventArgs<TMessage>> messageReceived = this.MessageReceived;
if (messageReceived != null)
{
messageReceived(this, new MessageReceivedEventArgs<TMessage>(message));
}
}
private void RunAsync()
{
while (this._continue)
{
TMessage message = default(TMessage);
bool flag = false;
try
{
lock (this._receivingLock)
{
this._receiving = true;
}
message = this.Channel.Receive();
flag = true;
lock (this._receivingLock)
{
this._receiving = false;
}
Thread.Sleep(0);
}
catch (ThreadInterruptedException)
{
}
if (!this._continue)
{
if (flag)
{
this.Channel.Send(message);
return;
}
break;
}
this.OnMessageReceived(message);
}
}
private void SafeInterrupt()
{
lock (this._receivingLock)
{
lock (this._threadLock)
{
if (this._receiving && (this._receiverThread != null))
{
this._receiverThread.Interrupt();
}
}
}
}
// Properties
protected override bool CanRaiseEvents
{
get
{
return true;
}
}
public IChannel<TMessage> Channel
{
[CompilerGenerated]
get
{
return this.channel;
}
[CompilerGenerated]
private set
{
this.channel = value;
}
}
public bool IsActive
{
get
{
lock (this._controlLock)
{
return (this._receiverThread != null);
}
}
}
}
using System;
using System.Runtime.CompilerServices;
public class MessageReceivedEventArgs<TMessage> : EventArgs
{
// Fields
[CompilerGenerated]
private TMessage message;
// Methods
public MessageReceivedEventArgs(TMessage message)
{
this.Message = message;
}
// Properties
public TMessage Message
{
[CompilerGenerated]
get
{
return this.message;
}
[CompilerGenerated]
private set
{
this.message = value;
}
}
}
using System.Threading;
public class BlockingChannel<TMessage> : IChannel<TMessage>
{
// Fields
private TMessage _message;
private EventWaitHandle _messageReceiveEvent;
private EventWaitHandle _messageReceiveyEvent;
private object _sendLock;
private ChannelState _state;
private object _stateLock;
// Methods
public BlockingChannel()
{
this._state = ChannelState.Open;
this._stateLock = new object();
this._messageReceiveyEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
this._messageReceiveEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
this._sendLock = new object();
}
public TMessage Receive()
{
this.State = ChannelState.WaitingForSend;
this._messageReceiveyEvent.WaitOne();
this._messageReceiveEvent.Set();
this.State = ChannelState.Open;
return this._message;
}
public void Send(TMessage message)
{
lock (this._sendLock)
{
this._message = message;
this.State = ChannelState.WaitingForReceive;
this._messageReceiveyEvent.Set();
this._messageReceiveEvent.WaitOne();
}
}
// Properties
public bool CanReceive
{
get
{
return true;
}
}
public bool CanSend
{
get
{
return true;
}
}
public ChannelState State
{
get
{
lock (this._stateLock)
{
return this._state;
}
}
private set
{
lock (this._stateLock)
{
this._state = value;
}
}
}
}
Pretty old but this is the good one that I know off http://www.codeproject.com/KB/cs/inprocessasynservicesincs.aspx
Use .NET 4 tasks.
var t = Task<int>.Factory.StartNew(() => ProcessItem());
Use the ConcurrencyOptions to set the maximum degree of parallelism on that processing.
If you want to roll it yourself, use BlockingCollection<T> which provides blocking and bounding capabilities for thread-safe collections and implement a separate thread (or threads) for the consumer.

Categories