Observer Pattern Closing Observable While Notifying - c#

I have a observable object that creates a UDP socket. This object has methods to send packets from that UDP socket and a thread to listen for received packets and invoke the PacketReceived event when a packet is received. My question is how should I handle the case when close method of the observer is called while the listener thread is busy invoking PacketReceived event. I can think of 2 solutions.
Close method immediately returns and listener thread ends after finished invoking the PacketReceived event. But with this solution listener thread could be still alive after calling the close method. So after the close method returns if I try to close another object that is used in a method that subscribed to PacketReceived event there will be a chance UDP listener thread try to access it after it is closed.
Thread that calls the close method waits for the listener thread to finish its work then closes the object. So after the close method returns it is guaranteed no other listener event will be invoked. So after that thread that calls the close method can close other objects that could be used by the UDP listener thread. But the problem is if the thread that calls the close method holds a lock and UDP listener thread tries to hold the same lock while invoking there will be a deadlock.
What is the preferred solution to this problem.

The second option is the better one. For this you can use semaphores. As #Fildor has stated, we have no code to go on, so this will be a "sketch" rather than a direct solution.
It sounds like you can use a simple SemaphoreSlim object to control this problem
var semaphore = new SemaphoreSlim(1, 1);
await semaphore.WaitAsync();
try
{
// Only one thread at a time can access this.
}
...
finally
{
semaphore.Release();
}
Obviously, you are needing cross class safty here, so making a class with a semaphore that is accessable from both places shpuld be enough.
Depanding on your use case and the latency required, you could also use a ConcurrentDictionary<string, SemaphoreSlim>, that is a concurrent dictionary of semaphores - here the key would be some kind of unique identifier that the thread that calls the close method and the listner thread both have access to. Then you can do something like
private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphoreDictionary =
new ConcurrentDictionary<string, SemaphoreSlim>();
...
var semaphore = _semaphoreDictionary.GetOrAdd(someUniqueKeyForTheThreadPair, new SemaphoreSlim(1, 1));
await semaphore.WaitAsync();
try
{
// Only one thread at a time can access this.
}
...
finally
{
semaphore.Release();
_semaphoreDictionary.Remove(someUniqueKeyForTheThreadPair, out _);
}
Without seeing any of your code, that is the best I can offer.

Related

C# keep event handling thread alive in CPU friendly way

I would like to run 10 threads in parallel. Each thread contains code that handles serial port communication (Using the 'SerialPort' class). Some of the features are:
Code for handling the event that is raised when the RS232 device returns data.
Code for handling Timer events that are raised when the RS232 device does not return data within a predefined time frame.
As you can see each thread handles some asynchronous events initialized and started from the thread itself. So the thread needs to keep itself alive until all events have been raised and processed. Based on the received data from the RS232 device the thread knows when the work is done and the thread can kill itself.
Now my question: I would like to avoid using an infinite loop to keep the thread alive to avoid using a lot of CPU resources on nothing. Any idea how to do this and also avoiding that the thread blocks/stops itself?.
The most efficient way to keep the 10 threads idle based on a condition is to use a WaitHandle.
The ManualResetEvent class allows you to simply signal when you want to continue execution. You can signal multiple threads with the same handle.
class Work
{
public static void WorkMethod(object stateInfo)
{
Console.WriteLine("Work starting.");
((ManualResetEvent)stateInfo).WaitOne();
Console.WriteLine("Work ending.");
}
}
// Example:
ManualResetEvent manualEvent = new ManualResetEvent(false);
Thread newThread = new Thread(Work.WorkMethod);
newThread.Start(manualEvent);
// This will terminate all threads that are waiting on this handle:
manualEvent.Set();

C# blocking wait for response

I have stumbled upon this problem many times, mostly solved it with hacks, but would like to see a "proprer" way to do it.
I'm writing a communication protocol, very similar to RPC in a way that my endpoints ask "queries", to which they receive "replies".
Now... I would like to implement a function, called SendCommand, that would send out a query, and wait for the reply to that question, and return it.
So I could do something like
int outside_temp = SendCommand(What is the temperature outside).ToInt();
The problem with this is that the messages are send and received asynchronously, and I am notified by events that a new message has arrived, and what it was. I would need to block the thread until the reply to the mentioned query has arrived, extract its data content, and return it to the caller.
My problem is with blocking the thread. Blocking the thread is not a problem, we are talking about a multi-threaded app, so the UI would not freeze, etc., but the question is what is the correct way to achieve this?
I'm thinking something along the line of initializing a semaphore inside the SendCommand function, waiting for it, and release the semaphore in the message received event handler (after checking it was the correct message)?
Regards,
axos88
So your question is about blocking the current thread and wait for the answer?
I would use a ManualResetEvent to synchronise the caller and the callback.
Supposed you can send your rpc call via a Send method of an object which accepts a callback method, you can code your SendCommand method like this:
int SendCommand(int param)
{
ManualResetEvent mre = new ManualResetEvent(false);
// this is the result which will be set in the callback
int result = 0;
// Send an async command with some data and specify a callback method
rpc.SendAsync(data, (returnData) =>
{
// extract / process your return value and
// assign it to an outer scope variable
result = returnData.IntValue;
// signal the blocked thread to continue
mre.Set();
});
// wait for the callback
mre.WaitOne();
return result;
}
What you could do is, spin a new thread that calls SendCommand(..) and just wait far the thread with sleeping until your SendCommand sends a signal.
For example:
volatile bool commandCompleted=false;
Thread sendCommandThread=new Thread(()=>{
SendCommand(...,()=>{
commandCompleted=true;
})
while(!commandCompleted)
{
Thread.Sleep(100);
}
});

How do I block until a thread is returned to the pool?

As part of a windows service
I'm accepting incoming socket connection using
myListener.BeginAcceptSocket(acceptAsync, null)
The acceptAsync function executes on a seperate thread (just as expected).
When the service is requested to shutdown, I "signal" the threads that accepted and are currently working on the sockets, to finish up.
After signaling each thread to end,I need to block until they are all done. I have a list of threads, that I thought I could iterate through and Join each thread until they were all done.
Howerver it seems that these threads don't end, but return to the pool, so the Join will wait for ever.
How do I block until a thread is returned to the pool?
You shouldn't use Join in this case. Rather, you should use a series of WaitHandles (specifically, an AutoResetEvent or ManualResetEvent) which your threads will signal when they are done with their work.
You would then call the static WaitAll method on the WaitHandle class, passing all of the events to wait on.
The canonical pattern for doing this is to use a CountdownEvent. The main thread will increment the event to indicate that it is participating and the worker threads will do the same once they start. After the worker threads have finished they will decrement the event. When the main thread is ready to wait for completion it should decrement the event and then wait on it. If you are not using .NET 4.0 then you can get an implemention of a countdown event from part 4 of Joe Albahari's threading ebook.
public class Example
{
private CountdownEvent m_Finisher = new CountdownEvent(0);
public void MainThread()
{
m_Finisher.AddCount();
// Your stuff goes here.
// myListener.BeginAcceptSocket(OnAcceptSocket, null);
m_Finisher.Signal();
m_Finisher.Wait();
}
private void OnAcceptSocket(object state)
{
m_Finisher.AddCount()
try
{
// Your stuff goes here.
}
finally
{
m_Finisher.Signal();
}
}
}
The best way would be to change acceptAsync so that it signals on a semaphore, your main thread can then wait on that semaphore.
You don't have a lot of acces to or control over Threapool threads.

How to unblock ConnectNamedPipe and ReadFile? [C#]

I have a class (NamedPipeManager) which has a thread (PipeThread) that waits for a NamedPipe connection using (ConnectNamedPipe) and then reads (ReadFile) - these are blocking calls (not-overlapped) - however there comes a point when I want to unblock them - for example when the calling class tries to stop the NamedPipeManager...
How can I interupt it? Using Thread.abort? Thread.interrupt? Is there a proper way to handle this?
Refer to the code below which illustrates my current situation
main()
{
NamedPipeManager np = new NamedPipeManager();
... do stuff ...
... do stuff ...
np.Stop(); // at this point I want to stop waiting on a connection
}
class NamedPipeManager
{
private Thread PipeThread;
public NamedPipeManager
{
PipeThread = new Thread(new ThreadStart(ManagePipes));
PipeThread.IsBackground = true;
PipeThread.Name = "NamedPipe Manager";
PipeThread.Start();
}
private void ManagePipes()
{
handle = CreateNamedPipe(..., PIPE_WAIT, ...);
ConnectNamedPipe(handle, null); // this is the BLOCKING call waiting for client connection
ReadFile(....); // this is the BLOCKING call to readfile after a connection has been established
}
public void Stop()
{
/// This is where I need to do my magic
/// But somehow I need to stop PipeThread
PipeThread.abort(); //?? my gut tells me this is bad
}
};
So, in function Stop() - how would I gracefully unblock the call to ConnectNamedPipe(...) or ReadFile(...)?
Any help would be appreciated.
Thanks,
It seems to be working on VC6.0, WinXP if I try to interrupt ConnectNamedPipe by
DeleteFile("\\\\.\\pipe\\yourpipehere");
So just specify name, not handle.
Starting with Windows Vista, there is a CancelSynchronousIO operation available for threads. I don't think there is a C# wrapper for it, so you would need to use PInvoke to call it.
Before Vista, there isn't really a way to perform such an operation gracefully. I would advise against using thread cancellation (which might work, but doesn't qualify as graceful). Your best approach is to use overlapped IO.
Recently I was in a situation, I could not use the Async Overlapped IO. I was stuck on the server side within ConnectNamedPipe. To unlock the thread and free resources, I had to connect to the same pipe as a client for a split second.
Main thread receives the stop signal
Main thread sets the stop event for the listening thread
Main thread connects to the pipe
If succeeded (always) - closes the newly created handle immediately
Listener thread unlocks
Listener thread does whatever required
This worked for me very well.
To unblock ReadFile one needs to connect and write to the pipe. Same effect epected.

while(true) or a tcp listen : what is more efficient?

I want my program to continuously wait for a trigger in order to perform the next task.
One option is pooling: using an infinite loop e.g. while(true)
OR, Do TCP listen on a port with a relatively higher timeout.
I would like to know which one of these two techniques would be more efficient too keep my application alive?
I feel executing while(true) would be a killer and tcp listen might be a health option since the tcp listen would use hardware interrupt ?
Also, In .net winform applications we have the Application.Run() method that keeps the application alive. If anyone one knows what this method does internally pls share.
PS: I have already considered msmq option here ( which is equivalent to tcp listen ) but I do not want a dependency on msmq.
Unless you're actually waiting for something to happen on a TCP/IP port, you shouldn't (ab)use Listen.
An efficient method isAutoResetEvent that you signal when you want to trigger the processing of a task. This will make your thread sleep until it needs to do something, without any polling.
class TaskProcessor
{
AutoResetEvent newTaskHandle = new AutoResetEvent(false);
Queue<Task> taskQueue = new Queue<Task>();
object syncRoot = new object();
public void ProcessTasks()
{
while (true)
{
newTaskHandle.WaitOne();
Task task = null;
lock (syncRoot)
{
if (taskQueue.Count > 0)
{
task = taskQueue.Dequeue();
}
}
// Do task
}
}
public void AddTask(Task task)
{
lock (syncRoot)
{
taskQueue.Enqueue(task);
newTaskHandle.Set();
}
}
}
This will probably raise the question how you can abort processing tasks. You can use more than a single WaitHandler (from which AutoResetEvent inherits) and wait for any of them to occur:
WaitHandle[] handles = new WaitHandle[] { newTaskHandle, stopHandle };
int signalledHandle = WaitHandle.WaitAny(handles);
Alternatively, you could introduce a simple boolean and reuse the same event. That might actually be preferrable if you want to make sure all tasks are processed before stopping.
What is this trigger's source ? Same application, same PC, network ?
Same application: use AutoResetEvent
Another application on the same PC: use a Mutex or Semaphore
Yes TCP listen would be the better option when the trigger source is another machine.
If your WinForms application doesn't end when you close the last windows most likely hou have some thread left running
I would consider putting your section of code into a separate thread and let the thread do the waiting to free up your UI, just have your UI listen for the event:
var tcpConnectionMade = new AutoResetEvent(false);
System.Threading.ThreadPool.QueueUserWorkItem(delegate
{
// listen for TCP connection
...
// once connected
tcpConnectionMade.Set();
});
// wait for TCP connection
WaitHandle.WaitOne(tcpConnectionMade);
// do something when connected...

Categories