Is it possible to remove ExecutionContext and Thread allocations when using SocketAsyncEventArgs? - c#

If you profile a simple client application that uses SocketAsyncEventArgs, you will notice Thread and ExecutionContext allocations.
The source of the allocations is SocketAsyncEventArgs.StartOperationCommon that creates a copy of the ExecutionContext with ExecutionContext.CreateCopy().
ExecutionContext.SuppressFlow seems like a good way to suppress this allocation. However this method itself will generate allocations when ran in a new thread.
How can I avoid these allocations?

SocketAsyncEventArgs
public class SocketAsyncEventArgs : EventArgs, IDisposable {
//...
// Method called to prepare for a native async socket call.
// This method performs the tasks common to all socket operations.
internal void StartOperationCommon(Socket socket) {
//...
// Prepare execution context for callback.
if (ExecutionContext.IsFlowSuppressed()) {
// This condition is what you need to pass.
// Fast path for when flow is suppressed.
m_Context = null;
m_ContextCopy = null;
} else {
// Flow is not suppressed.
//...
// If there is an execution context we need
//a fresh copy for each completion.
if(m_Context != null) {
m_ContextCopy = m_Context.CreateCopy();
}
}
// Remember current socket.
m_CurrentSocket = socket;
}
[Pure]
public static bool IsFlowSuppressed()
{
return Thread.CurrentThread.GetExecutionContextReader().IsFlowSuppressed;
}
//...
}
ExecutionContext
[Serializable]
public sealed class ExecutionContext : IDisposable, ISerializable
{
//...
// Misc state variables.
private ExecutionContext m_Context;
private ExecutionContext m_ContextCopy;
private ContextCallback m_ExecutionCallback;
//...
internal struct Reader
{
ExecutionContext m_ec;
//...
public bool IsFlowSuppressed
{
#if !FEATURE_CORECLR
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
get { return IsNull ? false : m_ec.isFlowSuppressed; }
}
} //end of Reader
internal bool isFlowSuppressed
{
get
{
return (_flags & Flags.IsFlowSuppressed) != Flags.None;
}
set
{
Contract.Assert(!IsPreAllocatedDefault);
if (value)
_flags |= Flags.IsFlowSuppressed;
else
_flags &= ~Flags.IsFlowSuppressed;
}
}
[System.Security.SecurityCritical] // auto-generated_required
public static AsyncFlowControl SuppressFlow()
{
if (IsFlowSuppressed())
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes"));
}
Contract.EndContractBlock();
AsyncFlowControl afc = new AsyncFlowControl();
afc.Setup();
return afc;
}
//...
}//end of ExecutionContext.
AsyncFlowControl
public struct AsyncFlowControl: IDisposable
{
private bool useEC;
private ExecutionContext _ec;
//...
[SecurityCritical]
internal void Setup()
{
useEC = true;
Thread currentThread = Thread.CurrentThread;
_ec = currentThread.GetMutableExecutionContext();
_ec.isFlowSuppressed = true;
_thread = currentThread;
}
}
Thread
// deliberately not [serializable]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(_Thread))]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class Thread : CriticalFinalizerObject, _Thread
{
//...
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal ExecutionContext.Reader GetExecutionContextReader()
{
return new ExecutionContext.Reader(m_ExecutionContext);
}
}
The only way to set isFlowSuppressed to true, to pass the condition in the StartOperationCommon method, is by calling Setup method, and the only call to Setup is in SuppressFlow method, wich you have discussed.
As you can see, SuppressFlow is the only solution.

Actually, SuppressFlow doesn't allocate. It returns a AsyncFlowControl, which is a struct. The proper solution basically is to call SendAsync and ReceiveAsync as follows:
public static bool SendAsyncSuppressFlow(this Socket self, SocketAsyncEventArgs e)
{
var control = ExecutionContext.SuppressFlow();
try
{
return self.SendAsync(e);
}
finally
{
control.Undo();
}
}
public static bool ReceiveAsyncSuppressFlow(this Socket self, SocketAsyncEventArgs e)
{
var control = ExecutionContext.SuppressFlow();
try
{
return self.ReceiveAsync(e);
}
finally
{
control.Undo();
}
}
I created these extension methods to make this a bit simpler and more explicit.
Traces with dotMemory showed that memory allocations really do go down to zero.

Related

Producer/ Consumer pattern using threads and EventWaitHandle

I guess it is sort of a code review, but here is my implementation of the producer / consumer pattern. What I would like to know is would there be a case in which the while loops in the ReceivingThread() or SendingThread() methods might stop executing. Please note that EnqueueSend(DataSendEnqeueInfo info) is called from multiple different threads and I probably can't use tasks here since I definitely have to consume commands in a separate thread.
private Thread mReceivingThread;
private Thread mSendingThread;
private Queue<DataRecievedEnqeueInfo> mReceivingThreadQueue;
private Queue<DataSendEnqeueInfo> mSendingThreadQueue;
private readonly object mReceivingQueueLock = new object();
private readonly object mSendingQueueLock = new object();
private bool mIsRunning;
EventWaitHandle mRcWaitHandle;
EventWaitHandle mSeWaitHandle;
private void ReceivingThread()
{
while (mIsRunning)
{
mRcWaitHandle.WaitOne();
DataRecievedEnqeueInfo item = null;
while (mReceivingThreadQueue.Count > 0)
{
lock (mReceivingQueueLock)
{
item = mReceivingThreadQueue.Dequeue();
}
ProcessReceivingItem(item);
}
mRcWaitHandle.Reset();
}
}
private void SendingThread()
{
while (mIsRunning)
{
mSeWaitHandle.WaitOne();
while (mSendingThreadQueue.Count > 0)
{
DataSendEnqeueInfo item = null;
lock (mSendingQueueLock)
{
item = mSendingThreadQueue.Dequeue();
}
ProcessSendingItem(item);
}
mSeWaitHandle.Reset();
}
}
internal void EnqueueRecevingData(DataRecievedEnqeueInfo info)
{
lock (mReceivingQueueLock)
{
mReceivingThreadQueue.Enqueue(info);
mRcWaitHandle.Set();
}
}
public void EnqueueSend(DataSendEnqeueInfo info)
{
lock (mSendingQueueLock)
{
mSendingThreadQueue.Enqueue(info);
mSeWaitHandle.Set();
}
}
P.S the idea here is that am using WaitHandles to put thread to sleep when the queue is empty, and signal them to start when new items are enqueued.
UPDATE
I am just going to leave this https://blogs.msdn.microsoft.com/benwilli/2015/09/10/tasks-are-still-not-threads-and-async-is-not-parallel/ ,for people who might be trying to implement Producer/Consumer pattern using TPL or tasks.
Use a BlockingCollection instead of Queue, EventWaitHandle and lock objects:
public class DataInfo { }
private Thread mReceivingThread;
private Thread mSendingThread;
private BlockingCollection<DataInfo> queue;
private CancellationTokenSource receivingCts = new CancellationTokenSource();
private void ReceivingThread()
{
try
{
while (!receivingCts.IsCancellationRequested)
{
// This will block until an item is added to the queue or the cancellation token is cancelled
DataInfo item = queue.Take(receivingCts.Token);
ProcessReceivingItem(item);
}
}
catch (OperationCanceledException)
{
}
}
internal void EnqueueRecevingData(DataInfo info)
{
// When a new item is produced, just add it to the queue
queue.Add(info);
}
// To cancel the receiving thread, cancel the token
private void CancelReceivingThread()
{
receivingCts.Cancel();
}
Personally, for simple producer-consumer problems, I would just use BlockingCollection. There would be no need to manually code your own synchronization logic. The consuming threads will also block if there are no items present in the queue.
Here is what your code might look like if you use this class:
private BlockingCollection<DataRecievedEnqeueInfo> mReceivingThreadQueue = new BlockingCollection<DataRecievedEnqeueInfo>();
private BlockingCollection<DataSendEnqeueInfo> mSendingThreadQueue = new BlockingCollection<DataSendEnqeueInfo>();
public void Stop()
{
// No need for mIsRunning. Makes the enumerables in the GetConsumingEnumerable() calls
// below to complete.
mReceivingThreadQueue.CompleteAdding();
mSendingThreadQueue.CompleteAdding();
}
private void ReceivingThread()
{
foreach (DataRecievedEnqeueInfo item in mReceivingThreadQueue.GetConsumingEnumerable())
{
ProcessReceivingItem(item);
}
}
private void SendingThread()
{
foreach (DataSendEnqeueInfo item in mSendingThreadQueue.GetConsumingEnumerable())
{
ProcessSendingItem(item);
}
}
internal void EnqueueRecevingData(DataRecievedEnqeueInfo info)
{
// You can also use TryAdd() if there is a possibility that you
// can add items after you have stopped. Otherwise, this can throw an
// an exception after CompleteAdding() has been called.
mReceivingThreadQueue.Add(info);
}
public void EnqueueSend(DataSendEnqeueInfo info)
{
mSendingThreadQueue.Add(info);
}
As suggested in comments, you also can give a try to the TPL Dataflow blocks.
As far as I can see, you have two similar pipelines, for receive and send, so I assume that your class hierarchy is like this:
class EnqueueInfo { }
class DataRecievedEnqeueInfo : EnqueueInfo { }
class DataSendEnqeueInfo : EnqueueInfo { }
We can assemble an abstract class which will encapsulate the logic for creating the pipeline, and providing the interface for processing the items, like this:
abstract class EnqueueInfoProcessor<T>
where T : EnqueueInfo
{
// here we will store all the messages received before the handling
private readonly BufferBlock<T> _buffer;
// simple action block for actual handling the items
private ActionBlock<T> _action;
// cancellation token to cancel the pipeline
public EnqueueInfoProcessor(CancellationToken token)
{
_buffer = new BufferBlock<T>(new DataflowBlockOptions { CancellationToken = token });
_action = new ActionBlock<T>(item => ProcessItem(item), new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount,
CancellationToken = token
});
// we are linking two blocks so all the items from buffer
// will flow down to action block in order they've been received
_buffer.LinkTo(_action, new DataflowLinkOptions { PropagateCompletion = true });
}
public void PostItem(T item)
{
// synchronously wait for posting to complete
_buffer.Post(item);
}
public async Task SendItemAsync(T item)
{
// asynchronously wait for message to be posted
await _buffer.SendAsync(item);
}
// abstract method to implement
protected abstract void ProcessItem(T item);
}
Note that you also can encapsulate the link between two blocks by using the Encapsulate<TInput, TOutput> method, but in that case you have to properly handle the Completion of the buffer block, if you're using it.
After this, we just need to implement two methods for receive and send handle logic:
public class SendEnqueueInfoProcessor : EnqueueInfoProcessor<DataSendEnqeueInfo>
{
SendEnqueueInfoProcessor(CancellationToken token)
: base(token)
{
}
protected override void ProcessItem(DataSendEnqeueInfo item)
{
// send logic here
}
}
public class RecievedEnqueueInfoProcessor : EnqueueInfoProcessor<DataRecievedEnqeueInfo>
{
RecievedEnqueueInfoProcessor(CancellationToken token)
: base(token)
{
}
protected override void ProcessItem(DataRecievedEnqeueInfo item)
{
// recieve logic here
}
}
You also can create more complicated pipeline with TransformBlock<DataRecievedEnqeueInfo, DataSendEnqeueInfo>, if your message flow is about a ReceiveInfo message became SendInfo.

Cancelling a Task when an object is Finalized

I have a class which starts a Task and want to ensure that the Task stops when the object is garbage collected.
I have implemented the IDisposable pattern to ensure that if the object is disposed manually or used within a using block, then the Task stops correctly. However, I cant guarantee that the end user will call Dispose() or use the object within a using block. I know that the Garbage Collector will eventually call the Finalizer - does this mean that the task is left running?
public class MyClass : IDisposable
{
private readonly CancellationTokenSource feedCancellationTokenSource =
new CancellationTokenSource();
private readonly Task feedTask;
public MyClass()
{
feedTask = Task.Factory.StartNew(() =>
{
while (!feedCancellationTokenSource.IsCancellationRequested)
{
// do finite work
}
});
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
feedCancellationTokenSource.Cancel();
feedTask.Wait();
feedCancellationTokenSource.Dispose();
feedTask.Dispose();
}
}
~MyClass()
{
Dispose(false);
}
}
It was suggested in this question to add a volatile bool which is set from the Finalizer and observed from the task. Is this recommended, or is there a better way to achieve what I need?
(I'm using .NET 4 hence the use of TaskFactory.StartNew rather than Task.Run)
EDIT:
To give some context to the question - which is not actually shown in the above code snippet: I am creating a Network client class which has a mechanism to keep alive by regularly sending packets to the server. I chose not to put all this detail in the example as it wasn't relevant to my specific question. However, what I actually want is the ability for the user to set a KeepAlive boolean property to true, which will start a task to send data to the server every 60 seconds. If the user sets the property to false then the task stops. IDisposable got me 90% of the way there, however it relies on the user disposing it properly (explicitly or via using). I don't want to expose keep alive tasks to the user for them to cancel explicitly, I just want a "simple" KeepAlive = true/false to start/stop the task AND I want the task to stop when the user is finished with the object - even if they don't dispose of it properly. I'm starting to think that this isn't possible!
I'll sketch an answer. I'm not 100% confident that this will work. Finalization is a complicated issue and I'm not proficient in it.
There can be no object reference from the task to whatever object is supposed to be finalized.
You can't touch other objects from a finalizer that are not known to be safe. The built-in .NET classes do not usually document this safety property. You can't rely on that (usually).
class CancellationFlag { public volatile bool IsSet; }
You can now share an instance of this class between the task and MyClass. The task must poll the flag and MyClass must set it.
In order to ensure that the task never accidentally references the outer object I'd structure the code like this:
Task.Factory.StartNew(TaskProc, state); //no lambda
static void TaskProc(object state) { //static
}
This way you can explicitly thread any state through state. This would, at least, be an instance of CancellationFlag but under no circumstances a reference to MyClass.
I created the program below to explore the differences...
From my observations with it, it looks like it makes no difference whether it's a cancellation token or a volatile bool, what really matters is that the Task.StartNew method isn't called using a lambda expression.
Edit: to clarify: if the lambda refers to a static method, it's actually fine: the problem comes when the lambda causes a reference to the containing class to be included: so either a reference to a member variable of the parent class or else a reference to an instance method of the parent class.
Please do give this a try and let me know if you come to the same conclusion.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
Logger.LogFile = #"c:\temp\test\log.txt";
Task.Run(() =>
{
// two instances (not disposed properly)
// if left to run, this background task keeps running until the application exits
var c1 = new MyClassWithVolatileBoolCancellationFlag();
// if left to run, this background task cancels correctly
var c2 = new MyClassWithCancellationSourceAndNoLambda();
//
var c3 = new MyClassWithCancellationSourceAndUsingTaskDotRun();
//
var c4 = new MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference();
}).GetAwaiter().GetResult();
// instances no longer referenced at this point
Logger.Log("Press Enter to exit");
Console.ReadLine(); // press enter to allow the console app to exit normally: finalizer gets called on both instances
}
static class Logger
{
private static object LogLock = new object();
public static string LogFile;
public static void Log(string toLog)
{
try
{
lock (LogLock)
using (var f = File.AppendText(LogFile))
f.WriteLine(toLog);
Console.WriteLine(toLog);
}
catch (Exception ex)
{
Console.WriteLine("Logging Exception: " + ex.ToString());
}
}
}
// finalizer gets called eventually (unless parent process is terminated)
public class MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference : IDisposable
{
private CancellationTokenSource cts = new CancellationTokenSource();
private readonly Task feedTask;
public MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference()
{
Logger.Log("New MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference Instance");
var token = cts.Token; // NB: by extracting the struct here (instead of in the lambda in the next line), we avoid the parent reference (via the cts member variable)
feedTask = Task.Run(() => Background(token)); // token is a struct
}
private static void Background(CancellationToken token) // must be static or else a reference to the parent class is passed
{
int i = 0;
while (!token.IsCancellationRequested) // reference to cts means this class never gets finalized
{
Logger.Log("Background task for MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference running. " + i++);
Thread.Sleep(1000);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
cts.Cancel();
if (disposing)
{
feedTask.Wait();
feedTask.Dispose();
Logger.Log("MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference Disposed");
}
else
{
Logger.Log("MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference Finalized");
}
}
~MyClassWithCancellationSourceAndUsingTaskDotRunButNoParentReference()
{
Dispose(false);
}
}
// finalizer doesn't get called until the app is exiting: background process keeps running
public class MyClassWithCancellationSourceAndUsingTaskDotRun : IDisposable
{
private CancellationTokenSource cts = new CancellationTokenSource();
private readonly Task feedTask;
public MyClassWithCancellationSourceAndUsingTaskDotRun()
{
Logger.Log("New MyClassWithCancellationSourceAndUsingTaskDotRun Instance");
//feedTask = Task.Factory.StartNew(Background, cts.Token);
feedTask = Task.Run(() => Background());
}
private void Background()
{
int i = 0;
while (!cts.IsCancellationRequested) // reference to cts & not being static means this class never gets finalized
{
Logger.Log("Background task for MyClassWithCancellationSourceAndUsingTaskDotRun running. " + i++);
Thread.Sleep(1000);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
cts.Cancel();
if (disposing)
{
feedTask.Wait();
feedTask.Dispose();
Logger.Log("MyClassWithCancellationSourceAndUsingTaskDotRun Disposed");
}
else
{
Logger.Log("MyClassWithCancellationSourceAndUsingTaskDotRun Finalized");
}
}
~MyClassWithCancellationSourceAndUsingTaskDotRun()
{
Dispose(false);
}
}
// finalizer gets called eventually (unless parent process is terminated)
public class MyClassWithCancellationSourceAndNoLambda : IDisposable
{
private CancellationTokenSource cts = new CancellationTokenSource();
private readonly Task feedTask;
public MyClassWithCancellationSourceAndNoLambda()
{
Logger.Log("New MyClassWithCancellationSourceAndNoLambda Instance");
feedTask = Task.Factory.StartNew(Background, cts.Token);
}
private static void Background(object state)
{
var cancelled = (CancellationToken)state;
if (cancelled != null)
{
int i = 0;
while (!cancelled.IsCancellationRequested)
{
Logger.Log("Background task for MyClassWithCancellationSourceAndNoLambda running. " + i++);
Thread.Sleep(1000);
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
cts.Cancel();
if (disposing)
{
feedTask.Wait();
feedTask.Dispose();
Logger.Log("MyClassWithCancellationSourceAndNoLambda Disposed");
}
else
{
Logger.Log("MyClassWithCancellationSourceAndNoLambda Finalized");
}
}
~MyClassWithCancellationSourceAndNoLambda()
{
Dispose(false);
}
}
// finalizer doesn't get called until the app is exiting: background process keeps running
public class MyClassWithVolatileBoolCancellationFlag : IDisposable
{
class CancellationFlag { public volatile bool IsSet; }
private CancellationFlag cf = new CancellationFlag();
private readonly Task feedTask;
public MyClassWithVolatileBoolCancellationFlag()
{
Logger.Log("New MyClassWithVolatileBoolCancellationFlag Instance");
feedTask = Task.Factory.StartNew(() =>
{
int i = 0;
while (!cf.IsSet)
{
Logger.Log("Background task for MyClassWithVolatileBoolCancellationFlag running. " + i++);
Thread.Sleep(1000);
}
});
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
cf.IsSet = true;
if (disposing)
{
feedTask.Wait();
feedTask.Dispose();
Logger.Log("MyClassWithVolatileBoolCancellationFlag Disposed");
}
else
{
Logger.Log("MyClassWithVolatileBoolCancellationFlag Finalized");
}
}
~MyClassWithVolatileBoolCancellationFlag()
{
Dispose(false);
}
}
}
}
Update:
Added a few more tests (now included above): and came to the same conclusion as "usr": the finalizer never gets called if there's a reference to the parent class (which makes sense: an active reference exists, therefore the GC doesn't kick in)

Creating class to work with Serial Port

My Goal: I have HASP with whom I need to communicate using Serial port.
The thing is many functions from different threads may want to communicate to this HASP - and I want some synchronization to occur.
What I did: I created wrapper class called HASPClass. Looks like this:
class HASPCLass
{
SerialPort m_port;
HASPClass(..)
{
//.. Init some other properties
m_port.Open();
//..
}
void CustomWriteToHASP()
{
//.. Do something
m_port.Write(...);
}
void CustomReadHASP()
{
//.. Do something
m_port.Read(...);
}
void Close ()
{
//Some code to close m_port
};
}
Usage of this class would be:
Function1 from some thread:
HASPClass o = new HASPClass(..);
o.CustomWriteToHASP(..)
Function2 from other thread:
HASPClass o1 = new HASPClass(..);
o1.CustomReadHASP(..)
Problem1: Now if o didn't close the m_port - constructor of o1 will throw since port is open.
I want to avoid this and make o1 wait for o to finish job.
What I thought: Maybe I should make m_port static - and put static lock everywhere it is used in HASPClass, will it solve above problem? Also the constructor will be changed to only open static m_port if it is closed. Will this approach solve most of the problems I outlined before?
Update: My other problem is that different objects might specify different parameters (baud rate etc.) in constructor - so I encounter a problem :( since I have single static m_port. :(. What to do in such case?? (I could relax this requirement and say all objects will put same parameters in constructor, but will it help?)
A simple singleton pattern might look something like this:
class HASPClass
{
private static HASPClass _instance;
private HASPClass(..)
{
//.. Init some other properties
}
public static GetInstance(...)
{
// Note, if called with different parameters then this will be
// quite a bit more complicated
if (_instance == null)
{
_instance = new HASPClass(...)
}
return _instance;
}
}
Now when you call it, you'd do something like:
HASPClass o = HASPClass.GetInstance(..);
o.CustomWriteToHASP(..)
But...since you are multithreading, this pattern won't be safe. You'll need to implement some locking around the critical GetInstance section to ensure that you don't create more than one object. So you could do something like:
private static object lockObj = new object();
public static GetInstance(...)
{
// Note, if called with different parameters then this will be
// quite a bit more complicated
if (_instance == null)
{
lock (lockObj)
{
if (_instance == null)
{
_instance = new HASPClass(...)
}
}
}
return _instance;
}
Better than manually locking would be to use Lazy, but that might be complicated if you need to pass parameters. If (as I assume) those parameters are only ever passed once, you might want to have a separate initialization function that will store those parameters so you don't need to pass them when you get your instance.
If the parameters are the same every time, you could maybe try something like this:
class HASPClass
{
private static ParameterObject _parameters;
private static Lazy<HASPClass> _instance = new Lazy<HASPClass>(() =>
{
if (_parameters == null)
{
throw new InvalidOperationException("Can get instance before initializing");
}
return new HASPClass(_parameters);
});
public static HASPClass Instance
{
get { return _instance.Value; }
}
private HASPClass(ParametersObject parameters)
{
// create and populate your object using values from parameters
}
public static void Initialize(ParameterObject parameters)
{
if (_parameters != null)
{
// you might throw an exception here if this is not allowed
// Or you might drop and recreate your object if it is allowed
}
_parameters = parameters;
}
}
You may or may not need to have locking around Initialize, but the idea would be that you'd probably call Initialize first from a parent thread so that it never needs to be called again from any other thread.
class HASPCLass
{
static SerialPort m_port;
HASPClass(..)
{
lock(m_port)
{
if (!Initialized())
{
Initialize();
}
}
}
void Close ()
{
lock(m_port)
{
if (Initialized())
{
Uninitialize();
}
}
}
}
Here is one more variant of the code for you. It should work in any case. It reopens the port in case of different baud rate requested.
class HASPCLass
{
private static SerialPort m_port;
private static bool m_initialized;
private static int m_baudRate;
public HASPClass(int baudRate)
{
lock(m_port)
{
if (!m_initialized)
{
Initialize(baudRate);
}
}
}
private Initialize()
{
m_port.open(baudRate);
m_baudRate = baudRate;
m_initialized = true;
}
private Uninitialize()
{
m_port.close();
m_initialized = false;
}
private ReinitializeIfNeeded(int baudRate)
{
if (baudRate != m_baudRate)
{
Uninitialize();
Initialize(baudRate);
}
}
public void Read(int baudRate, out buff)
{
lock(m_port)
{
ReinitializeIfNeeded(baudRate);
m_port.Read(out buff);
}
}
public void Write(int baudRate, in buff)
{
lock(m_port)
{
ReinitializeIfNeeded(baudRate);
m_port.Write(buff);
}
}
public void Close()
{
lock(m_port)
{
if (m_initialized)
{
Uninitialize();
}
}
}
}

How to let only one thread to run a critical section while discarding the other threads without hang

I'm developing a windows service with .NET framework 4.0 and C#.
This service will open a socket to receive commands.
I have this socket listener class:
public class SocketListener
{
private System.Net.Sockets.TcpListener m_server;
public SQLServerSocketListener()
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 5445);
m_server = new System.Net.Sockets.TcpListener(ip);
}
public void Start()
{
m_server.Start();
m_server.BeginAcceptTcpClient(new AsyncCallback(Callback), m_server);
}
public void Stop()
{
if (m_server != null)
m_server.Stop();
}
private void Callback(IAsyncResult ar)
{
if (!(m_server.Server.IsBound) ||
(m_server.Server == null))
return;
TcpClient client;
try
{
client = m_server.EndAcceptTcpClient(ar);
}
catch (ObjectDisposedException)
{
//Listener canceled
return;
}
DataHandler dataHandler = new DataHandler(client);
ThreadPool.QueueUserWorkItem(dataHandler.HandleClient, client);
m_server.BeginAcceptTcpClient(new AsyncCallback(Callback), m_server);
}
}
And this class to process the commands received through the socket:
class DataHandler
{
private bool m_disposed = false;
private TcpClient m_controlClient;
private IPEndPoint m_remoteEndPoint;
private string m_clientIP;
private NetworkStream m_controlStream;
private StreamReader m_controlReader;
public DataHandler(TcpClient client)
{
m_controlClient = client;
}
public void HandleClient(object obj)
{
m_remoteEndPoint = (IPEndPoint)m_controlClient.Client.RemoteEndPoint;
m_clientIP = m_remoteEndPoint.Address.ToString();
m_controlStream = m_controlClient.GetStream();
m_controlReader = new StreamReader(m_controlStream, true);
string line;
try
{
while (((line = m_controlReader.ReadLine()) != null) ||
(m_controlClient == null) ||
(!m_controlClient.Connected))
{
CommandHandler.ProcessCommand(line);
}
}
catch (Exception ex)
{
Console.WriteLine("CodeServerService.DataHandler error: {0}", ex.Message);
}
finally
{
Dispose();
}
}
}
And, the CommandHandler:
class CommandHandler
{
public static void ProcessCommand(string command, string connStringINICIC, string connStringTRZIC, byte codeLevel)
{
switch (command)
{
case "GetNewCodes<EOF>":
CodesIncremental.GetNewCodes();
break;
}
}
}
And CodesIncremental:
public class CodesIncremental
{
public static bool GetNewCodes()
{
[ ... ]
}
}
My problem is that I can receive GetNewCodes<EOF> command before the first one finish. So, I need to don't let GetNewCodes<EOF>runs if there is another GetNewCodes<EOF> running.
How can I don't let run CodesIncremental.GetNewCodes(); if this code its running in another thread?
I need something to discard the commands received while CodesIncremental.GetNewCodes(); is running.
In pseudo code:
If CodesIncremental.GetNewCodes(); is running do nothing.
This version does not block. CompareExchange ensures atomicity, so only one thread will swap the value of the _running variable, the rest of threads will just return inmediately.
public class CodesIncremental
{
static Int32 _running = 0;
public static bool GetNewCodes()
{
if (Interlocked.CompareExchange(ref _running, 1, 0) == 1)
return false;
try
{
// Do stuff...
return true;
}
finally
{
_running = 0;
}
}
}
A difference than monitors or other synchronization methods, there is little contention on this method, and it is quite faster.
Maybe like this using AutoResetEvent:
public class CodesIncremental
{
private AutoResetEvent _event = new AutoResetEvent(true);
public static bool GetNewCodes()
{
if(!_event.WaitOne(0))
return true; //is running
try
{
/*
actions in case if isn't running
*/
}
finally
{
_event.Set();
}
return false;
}
}
EDIT: Update to address the modification of the question.
A simple way is to use the Monitor.TryEnter and Monitor.Exit
Just call the ExecuteGetNewCodeCommand for the processing of your "GetNewCode" command.
object _myLock = new object();
void ExecuteGetNewCodeCommand( ArgType args)
{
bool result = false;
try
{
result = Monitor.TryEnter(_myLock); // This method returns immediately
if( !result) // check if the lock is acquired.
return;
// Execute your command code here
}
finally
{
if(result) // release the lock.
Monitor.Exit(_myLock);
}
}
Old answer (before the modification of the question):
Think about using a queue and a Thread Pool.
Every time you receive a new Command (including "GetNewCode") insert it into a queue. In addition, you will have a Thread Pool that will read requests from the queue and execute them.
If you are using only one thread in the Thread pool, or a dedicated thread for this type of commands (where there are other threads for other requests/commands in the queue/queus), then only one "GetNewCode" request will be running at the same time.
This way you can control the number of threads your server will run. Thus, also the resources your server uses.
If you just synchronize (via locks or other mechanism) then there are a performance penalties. And maybe a denial of service, if you reached a thread limit. Let's say for somehow the execution of a request is taking too long (Maybe a deadlock in your code). If you will not use a Thread pool, and will execute the commands/requests on the same thread the client connected to your, then your sever may hang.
Though, If you will synchronize the threads inside the thread pool, then the server will not hang. Maybe it will be really slow to execute the requests, but it will still run and work.
There is a default .Net ThreadPool implementation at MSDN.
Add a lock to your CodesIncremental Class:
public class CodesIncremental
{
private object m_threadLock = new object();
public static bool GetNewCodes()
{
lock(m_threadLock)
{
[ ... ]
}
}
}
http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx
This way when your GetNewCodes method is called the first time the 'lock' statement will get an exclusive lock on the 'm_threadLock' object and only release it when the execution leaves the lock block, if any other thread calls the methods while the first thread is still inside the lock block it will not be able to get an exclusive lock and execution will suspend until it can.
Update:
Since you want to discard other calls try this:
public class CodesIncremental
{
private static object m_threadLock = new object();
private static bool m_running = false;
public static bool GetNewCodes()
{
lock(m_threadLock)
{
if(m_running)
{
return;
}
m_running = true;
}
try
{
[ ... ]
}
finally
{
m_running = false;
}
}
}
there might be better ways but this should do the trick.
Update 2: Hadn't seen the static

Is there a synchronization class that guarantee FIFO order in C#?

What is it and how to use?
I need that as I have a timer that inserts into DB every second, and I have a shared resource between timer handler and the main thread.
I want to gurantee that if the timer handler takes more than one second in the insertion the waited threads should be executed in order.
This is a sample code for my timer handler:
private void InsertBasicVaraibles(object param)
{
try
{
DataTablesMutex.WaitOne();//mutex for my shared resources
//insert into DB
}
catch (Exception ex)
{
//Handle
}
finally
{
DataTablesMutex.ReleaseMutex();
}
}
But currently the mutex does not guarantee any order.
You'll need to write your own class to do this, I found this example (pasted because it looks as though the site's domain has lapsed):
using System.Threading;
public sealed class QueuedLock
{
private object innerLock;
private volatile int ticketsCount = 0;
private volatile int ticketToRide = 1;
public QueuedLock()
{
innerLock = new Object();
}
public void Enter()
{
int myTicket = Interlocked.Increment(ref ticketsCount);
Monitor.Enter(innerLock);
while (true)
{
if (myTicket == ticketToRide)
{
return;
}
else
{
Monitor.Wait(innerLock);
}
}
}
public void Exit()
{
Interlocked.Increment(ref ticketToRide);
Monitor.PulseAll(innerLock);
Monitor.Exit(innerLock);
}
}
Example of usage:
QueuedLock queuedLock = new QueuedLock();
try
{
queuedLock.Enter();
// here code which needs to be synchronized
// in correct order
}
finally
{
queuedLock.Exit();
}
Source via archive.org
Just reading Joe Duffy's "Concurrent Programming on Windows" it sounds like you'll usually get FIFO behaviour from .NET monitors, but there are some situations where that won't occur.
Page 273 of the book says: "Because monitors use kernel objects internally, they exhibit the same roughly-FIFO behavior that the OS synchronization mechanisms also exhibit (described in the previous chapter). Monitors are unfair, so if another thread sneaks in and acquires the lock before an awakened waiting thread tries to acquire the lock, the sneaky thread is permitted to acquire the lock."
I can't immediately find the section referenced "in the previous chapter" but it does note that locks have been made deliberately unfair in recent editions of Windows to improve scalability and reduce lock convoys.
Do you definitely need your lock to be FIFO? Maybe there's a different way to approach the problem. I don't know of any locks in .NET which are guaranteed to be FIFO.
You should re-design your system to not rely on the execution order of the threads. For example, rather than have your threads make a DB call that might take more than one second, have your threads place the command they would execute into a data structure like a queue (or a heap if there is something that says "this one should be before another one"). Then, in spare time, drain the queue and do your db inserts one at a time in the proper order.
There is no guaranteed order on any built-in synchronisation objects: http://msdn.microsoft.com/en-us/library/ms684266(VS.85).aspx
If you want a guaranteed order you'll have to try and build something yourself, note though that it's not as easy as it might sound, especially when multiple threads reach the synchronisation point at (close to) the same time. To some extent the order they will be released will always be 'random' since you cannot predict in which order the point is reached, so does it really matter?
Actually the answers are good, but I solved the problem by removing the timer and run the method (timer-handler previously) into background thread as follows
private void InsertBasicVaraibles()
{
int functionStopwatch = 0;
while(true)
{
try
{
functionStopwatch = Environment.TickCount;
DataTablesMutex.WaitOne();//mutex for my shared resources
//insert into DB
}
catch (Exception ex)
{
//Handle
}
finally
{
DataTablesMutex.ReleaseMutex();
}
//simulate the timer tick value
functionStopwatch = Environment.TickCount - functionStopwatch;
int diff = INSERTION_PERIOD - functionStopwatch;
int sleep = diff >= 0 ? diff:0;
Thread.Sleep(sleep);
}
}
Follow up on Matthew Brindley's answer.
If converting code from
lock (LocalConnection.locker) {...}
then you could either do a IDisposable or do what I did:
public static void Locking(Action action) {
Lock();
try {
action();
} finally {
Unlock();
}
}
LocalConnection.Locking( () => {...});
I decided against IDisposable because it would creates a new invisible object on every call.
As to reentrancy issue I modified the code to this:
public sealed class QueuedLock {
private object innerLock = new object();
private volatile int ticketsCount = 0;
private volatile int ticketToRide = 1;
ThreadLocal<int> reenter = new ThreadLocal<int>();
public void Enter() {
reenter.Value++;
if ( reenter.Value > 1 )
return;
int myTicket = Interlocked.Increment( ref ticketsCount );
Monitor.Enter( innerLock );
while ( true ) {
if ( myTicket == ticketToRide ) {
return;
} else {
Monitor.Wait( innerLock );
}
}
}
public void Exit() {
if ( reenter.Value > 0 )
reenter.Value--;
if ( reenter.Value > 0 )
return;
Interlocked.Increment( ref ticketToRide );
Monitor.PulseAll( innerLock );
Monitor.Exit( innerLock );
}
}
In case anyone needs Matt's solution in F#
type internal QueuedLock() =
let innerLock = Object()
let ticketsCount = ref 0
let ticketToRide = ref 1
member __.Enter () =
let myTicket = Interlocked.Increment ticketsCount
Monitor.Enter innerLock
while myTicket <> Volatile.Read ticketToRide do
Monitor.Wait innerLock |> ignore
member __.Exit () =
Interlocked.Increment ticketToRide |> ignore
Monitor.PulseAll innerLock
Monitor.Exit innerLock
Elaborating on Matt Brindley's great answer so that it works with the using statement:
public sealed class QueuedLockProvider
{
private readonly object _innerLock;
private volatile int _ticketsCount = 0;
private volatile int _ticketToRide = 1;
public QueuedLockProvider()
{
_innerLock = new object();
}
public Lock GetLock()
{
return new Lock(this);
}
private void Enter()
{
int myTicket = Interlocked.Increment(ref _ticketsCount);
Monitor.Enter(_innerLock);
while (true)
{
if (myTicket == _ticketToRide)
{
return;
}
else
{
Monitor.Wait(_innerLock);
}
}
}
private void Exit()
{
Interlocked.Increment(ref _ticketToRide);
Monitor.PulseAll(_innerLock);
Monitor.Exit(_innerLock);
}
public class Lock : IDisposable
{
private readonly QueuedLockProvider _lockProvider;
internal Lock(QueuedLockProvider lockProvider)
{
_lockProvider = lockProvider;
_lockProvider.Enter();
}
public void Dispose()
{
_lockProvider.Exit();
}
}
}
Now use it like this:
QueuedLockProvider _myLockProvider = new QueuedLockProvider();
// ...
using(_myLockProvider.GetLock())
{
// here code which needs to be synchronized
// in correct order
}
NOTE: The examples provided are susceptible to Deadlocks.
Example:
QueuedLock queuedLock = new QueuedLock();
void func1()
{
try
{
queuedLock.Enter();
fubc2()
}
finally
{
queuedLock.Exit();
}
}
void func2()
{
try
{
queuedLock.Enter(); //<<<< DEADLOCK
}
finally
{
queuedLock.Exit();
}
}
Re. optional solution (inc. an optional IDisposable usage):
public sealed class QueuedLock
{
private class SyncObject : IDisposable
{
private Action m_action = null;
public SyncObject(Action action)
{
m_action = action;
}
public void Dispose()
{
lock (this)
{
var action = m_action;
m_action = null;
action?.Invoke();
}
}
}
private readonly object m_innerLock = new Object();
private volatile uint m_ticketsCount = 0;
private volatile uint m_ticketToRide = 1;
public bool Enter()
{
if (Monitor.IsEntered(m_innerLock))
return false;
uint myTicket = Interlocked.Increment(ref m_ticketsCount);
Monitor.Enter(m_innerLock);
while (true)
{
if (myTicket == m_ticketToRide)
return true;
Monitor.Wait(m_innerLock);
}
}
public void Exit()
{
Interlocked.Increment(ref m_ticketToRide);
Monitor.PulseAll(m_innerLock);
Monitor.Exit(m_innerLock);
}
public IDisposable GetLock()
{
if (Enter())
return new SyncObject(Exit);
return new SyncObject(null);
}
}
Usage:
QueuedLock queuedLock = new QueuedLock();
void func1()
{
bool isLockAquire = false;
try
{
isLockAquire = queuedLock.Enter();
// here code which needs to be synchronized in correct order
}
finally
{
if (isLockAquire)
queuedLock.Exit();
}
}
or:
QueuedLock queuedLock = new QueuedLock();
void func1()
{
using (queuedLock.GetLock())
{
// here code which needs to be synchronized in correct order
}
}

Categories

Resources