Mutex alternative for process synchronisation/signalling with async support? - c#

Is there anything except for Mutex to synchronise two processes in a fault-tolerant fashion? Please bear with me...
There is a process A, it's a bit flaky, it needs to start process B in the background and continue. If process A successfully does its thing, it needs to signal process B to dispose, and moves on (it doesn't terminate and thread is reused). If process A dies due to exception, termination, etc. process B needs to detect it quickly and dispose of itself on its own. Process A is not a "process" rather a library executed by various hosts hence process B can't just wait for process A's name to disappear.
Enter Mutex.
Here process A represented by a test fixture, if successful it'll call TestFixtureTearDown and move on, or test runner might be killed and TestFixtureTearDown is never executed. As with the actual process, TestFixtureTearDown might be called by a different thread to one that ran TestFixtureSetUp and created the mutex, hence ReleaseMutex sometimes throws ApplicationException : Object synchronization method was called from an unsynchronized block of code.
Can I force ReleaseMutex in TestFixtureTearDown if it's being executed by a different thread or abandon mutex some other way?
Is there an alternative to Mutex that I can use for such fault-tolerant "reverse" wait/monitor scenario? Preferably without implementing process A sending heartbeats to process B and process B tracking intervals and timing out? Mutex felt like such an elegant solution except for occasional ApplicationException on asyncs.
.
namespace ClassLibrary1
{
public class Class1
{
private Mutex _mutex;
private Process _process;
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
_mutex = new Mutex(true, "foo");
_process = Process.Start("ConsoleApplication1.exe");
}
[Test]
public void Test1() { /* Do stuff */ }
[Test]
public void Test2() { /* Do async stuff */ }
[TestFixtureTearDown]
public void TestFixtureTearDown()
{
_mutex.ReleaseMutex();
_process.WaitForExit();
}
}
}
.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var mutex = Mutex.OpenExisting("foo");
// Start doing stuff
try { mutex.WaitOne(); }
catch (AbandonedMutexException) { }
finally { mutex.ReleaseMutex(); }
// Finish doing stuff
}
}
}

Semaphores do not have thread affinity. You can release a semaphore on a different thread than it was acquired on. Use a semaphore with a count of 1.

I ended up using a mix of Mutex, Thread and ManualResetEvent. For the googling folk of the future here's a verbose test:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
namespace MutexResetEvent.Tests
{
public class Class1
{
private Mutex _mutex;
private Thread _thread;
private Process _process;
private ManualResetEvent _event;
[SetUp]
public void SetUp()
{
Console.WriteLine("SetUp: #{0}", Thread.CurrentThread.ManagedThreadId);
_event = new ManualResetEvent(false);
_thread = new Thread(() =>
{
Console.WriteLine("Thread: #{0}", Thread.CurrentThread.ManagedThreadId);
_mutex = new Mutex(true, "MutexResetEvent");
_process = new Process
{
StartInfo =
{
FileName = "MutexResetEvent.Worker.exe",
//UseShellExecute = false,
//RedirectStandardOutput = true
}
};
//_process.OutputDataReceived += (o, a) => Console.WriteLine(a.Data);
_process.Start();
//_process.BeginOutputReadLine();
while (!_event.WaitOne(1000))
Console.WriteLine("Thread: ...");
Console.WriteLine("Thread: #{0}", Thread.CurrentThread.ManagedThreadId);
_mutex.ReleaseMutex();
_process.WaitForExit();
});
}
[Test]
public void Test()
{
Console.WriteLine("Test: #{0}", Thread.CurrentThread.ManagedThreadId);
_thread.Start();
for (var i = 0; i < 3; i++)
{
Console.WriteLine("Test: ...");
Thread.Sleep(1000);
}
/*
if (Guid.NewGuid().GetHashCode() % 3 == 0)
Environment.Exit(1);
//*/
}
[TearDown]
public void TearDown()
{
Console.WriteLine("TearDown: #{0}", Thread.CurrentThread.ManagedThreadId);
Task.Run(() =>
{
Console.WriteLine("Task: #{0}", Thread.CurrentThread.ManagedThreadId);
_event.Set();
//_thread.Join();
}).Wait();
for (var i = 0; i < 3; i++)
{
Console.WriteLine("TearDown: ...");
Thread.Sleep(1000);
}
}
}
}
.
using System;
using System.Threading;
namespace MutexResetEvent.Worker
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Worker: #{0}", Thread.CurrentThread.ManagedThreadId);
var mutex = Mutex.OpenExisting("MutexResetEvent");
try
{
while (!mutex.WaitOne(1000))
Console.WriteLine("Worker: ...");
}
catch (AbandonedMutexException)
{
Console.WriteLine("Worker: AbandonedMutexException");
}
Console.WriteLine("Worker: #{0}", Thread.CurrentThread.ManagedThreadId);
mutex.ReleaseMutex();
Console.WriteLine("Worker: WOO HOO");
Console.ReadLine();
}
}
}

Related

Why thread-pool doesn't complete task till end? [duplicate]

This question already has answers here:
Wait for QueueUserWorkItem to Complete
(3 answers)
Closed 3 years ago.
I created very simple program and used Thread-pool for execute 3 task simultaneously. In this method 1 will print same message 9000 times (because using loop), method 2 and 3rd will print message 1 time. Now the problem is that, method 1 print message only few times and then program stop execution.
Some times not result display.
I know that if foreground thread will complete the task the all the background task will stop working. But how is it acceptable program stop working without completing task.
using System;
using System.Threading;
namespace ThreadingInCSharp
{
class Program
{
static void Main()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Method_1));
ThreadPool.QueueUserWorkItem(new WaitCallback(Method_2));
ThreadPool.QueueUserWorkItem(new WaitCallback(Method_3));
Thread.CurrentThread.IsBackground = false;
}
private static void Method_1(object obj)
{
for (int i = 0; i < 9000; i++)
{
Console.WriteLine("It's method 1");
}
}
private static void Method_2(object obj)
{
Console.WriteLine("It's method 2");
}
private static void Method_3(object obj)
{
Console.WriteLine("It's method 3");
}
}
}
Thread.CurrentThread.IsBackground = false;
That line will not do anything since there are no further instructions to wait for.
Simply add Console.ReadLine() and the end of Main.
static void Main()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Method_1));
ThreadPool.QueueUserWorkItem(new WaitCallback(Method_2));
ThreadPool.QueueUserWorkItem(new WaitCallback(Method_3));
Console.Write("Press ENTER to quit");
Console.ReadLine();
}
If you want to wait for all threads to complete, you can use thread synchronization objects like ManualResetEvent.
using System;
using System.Threading;
namespace ThreadingInCSharp
{
class Program
{
ManualResetEvent _method1Event = new ManualResetEvent(false);
ManualResetEvent _method2Event = new ManualResetEvent(false);
ManualResetEvent _method3Event = new ManualResetEvent(false);
static void Main()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Method_1));
ThreadPool.QueueUserWorkItem(new WaitCallback(Method_2));
ThreadPool.QueueUserWorkItem(new WaitCallback(Method_3));
WaitHandle.WaitAll(new[]{_method1Event, _method2Event, _method3Event});
}
private static void Method_1(object obj)
{
for (int i = 0; i < 9000; i++)
{
Console.WriteLine("It's method 1");
}
_method1Event.Set();
}
private static void Method_2(object obj)
{
Console.WriteLine("It's method 2");
_method2Event.Set();
}
private static void Method_3(object obj)
{
Console.WriteLine("It's method 3");
_method3Event.Set();
}
}
}
WaitHandle.WaitAll will wait until all three events have been signaled (i.e. the methods have completed their work).

Trigger an endless Thread Even when the Function Terminates

The question is that, what happens to a thread when the function has already been executed and the thread is started in that function. (please see an example below)
public int Intialise ()
{
int i = startServer();
Thread readall = new Thread(readAllMessage);
if (i == 1)
readall.Start();
else
MessageBox.Show("Connection Error");
return i;
}
I want 'readall' to continue (forever or till the application is closed) even if the function is executed. Is it possible? Because for me the thread stops immediately even when the true condition is met. Please shed some light.
OK, here is your code slightly modified to include the loop.
internal class Program
{
public static int Intialise()
{
int i = startServer();
Thread readall = new Thread(readAllMessage);
readall.IsBackground = true; // so that when the main thread finishes, the app closes
if (i == 1)
readall.Start();
else
Console.WriteLine("Error");
return i;
}
public static void readAllMessage()
{
while (true)
{
Console.WriteLine("reading...");
Thread.Sleep(500);
}
}
public static int startServer()
{
return 1;
}
private static void Main(string[] args)
{
var i = Intialise();
Console.WriteLine("Init finished, thread running");
Console.ReadLine();
}
}
when you run it, it will print:
Init finished, thread running
reading...
reading...
reading...
and when you press enter (see Console.ReadLine()) it will stop running.
If you change the IsBackground to TRUE it would not exit the process.
Here is an example of what you ask
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ForeverApp
{
class SomeObj
{
public void ExecuteForever()
{
while (true)
{
Thread.Sleep(1000);
Console.Write(".");
}
}
}
class Program
{
static void Main(string[] args)
{
SomeObj so = new SomeObj();
Thread thrd = new Thread(so.ExecuteForever);
thrd.Start();
Console.WriteLine("Exiting Main Function");
}
}
}

AutoResetEvent Reset immediately after Set

Consider the following pattern:
private AutoResetEvent signal = new AutoResetEvent(false);
private void Work()
{
while (true)
{
Thread.Sleep(5000);
signal.Set();
//has a waiting thread definitely been signaled by now?
signal.Reset();
}
}
public void WaitForNextEvent()
{
signal.WaitOne();
}
The purpose of this pattern is to allow external consumers to wait for a certain event (e.g. - a message arriving). WaitForNextEvent is not called from within the class.
To give an example that should be familiar, consider System.Diagnostics.Process. It exposes an Exited event, but it also exposes a WaitForExit method, which allows the caller to wait synchronously until the process exits. this is what I am trying to achieve here.
The reason I need signal.Reset() is that if a thread calls WaitForNextEvent after signal.Set() has already been called (or in other words, if .Set was called when no threads were waiting), it returns immediately, as the event has already been previously signaled.
The question
Is it guaranteed that a thread calling WaitForNextEvent() will be signaled before signal.Reset() is called? If not, what are other solutions for implementing a WaitFor method?
Instead of using AutoResetEvent or ManualResetEvent, use this:
public sealed class Signaller
{
public void PulseAll()
{
lock (_lock)
{
Monitor.PulseAll(_lock);
}
}
public void Pulse()
{
lock (_lock)
{
Monitor.Pulse(_lock);
}
}
public void Wait()
{
Wait(Timeout.Infinite);
}
public bool Wait(int timeoutMilliseconds)
{
lock (_lock)
{
return Monitor.Wait(_lock, timeoutMilliseconds);
}
}
private readonly object _lock = new object();
}
Then change your code like so:
private Signaller signal = new Signaller();
private void Work()
{
while (true)
{
Thread.Sleep(5000);
signal.Pulse(); // Or signal.PulseAll() to signal ALL waiting threads.
}
}
public void WaitForNextEvent()
{
signal.Wait();
}
There is no guarantee. This:
AutoResetEvent flag = new AutoResetEvent(false);
new Thread(() =>
{
Thread.CurrentThread.Priority = ThreadPriority.Lowest;
Console.WriteLine("Work Item Started");
flag.WaitOne();
Console.WriteLine("Work Item Executed");
}).Start();
// For fast systems, you can help by occupying processors.
for (int ix = 0; ix < 2; ++ix)
{
new Thread(() => { while (true) ; }).Start();
}
Thread.Sleep(1000);
Console.WriteLine("Sleeped");
flag.Set();
// Decomment here to make it work
//Thread.Sleep(1000);
flag.Reset();
Console.WriteLine("Finished");
Console.ReadLine();
won't print "Work Item Executed" on my system. If I add a Thread.Sleep between the Set and the Reset it prints it. Note that this is very processor dependent, so you could have to create tons of threads to "fill" the CPUs. On my PC it's reproducible 50% of the times :-)
For the Exited:
readonly object mylock = new object();
then somewhere:
lock (mylock)
{
// Your code goes here
}
and the WaitForExit:
void WaitForExit()
{
lock (mylock) ;
// exited
}
void bool IsExited()
{
bool lockTacken = false;
try
{
Monitor.TryEnter(mylock, ref lockTacken);
}
finally
{
if (lockTacken)
{
Monitor.Exit(mylock);
}
}
return lockTacken;
}
Note that the lock construct isn't compatible with async/await (as aren't nearly all the locking primitives of .NET)
I would use TaskCompletionSources:
private volatile TaskCompletionSource<int> signal = new TaskCompletionSource<int>();
private void Work()
{
while (true)
{
Thread.Sleep(5000);
var oldSignal = signal;
signal = new TaskCompletionSource<int>()
//has a waiting thread definitely been signaled by now?
oldSignal.SetResult(0);
}
}
public void WaitForNextEvent()
{
signal.Task.Wait();
}
By the time that the code calls SetResult, no new code entering WaitForNextEvent can obtain the TaskCompletionSource that is being signalled.
I believe it is not guaranteed.
However, your logic flow is not understood by me. If your main thread Sets the signal, why should it wait until that signal reaches its destination? Wouldn't it be better to continue your "after signal set" logic in that thread which was waiting?
If you cannot do that, I recommend you to use second WaitHandle to signal the first thread that the second one has reveiced the signal. But I cannot see any pros of such a strategy.

producer consumer using AutoReset Event in c#

Below code is not working usin Auto Reset event, what wrong i am doing ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Threaddd
{
class Program
{
static int num = 0;
static EventWaitHandle e = new AutoResetEvent(false);
static object o = new object();
static void Main(string[] args)
{
new Thread(Consumer).Start();
new Thread(Producer).Start();
}
static void Producer()
{
while (true)
{
if (num == 0)
{
num++;
Console.WriteLine("Produced " + num);
Thread.Sleep(1000);
e.Set();
e.WaitOne();
}
}
}
static void Consumer()
{
while (true)
{
if (num == 1)
{
Console.WriteLine("Consumed " + num);
Thread.Sleep(1000);
num--;
e.Set();
e.WaitOne();
}
else
{
e.WaitOne();
}
}
}
}
It looks like when the Producer thread calls e.Set(), it does not notify the Consumer thread immediately, so the Producer thread consumes the event when it calls e.WaitOne().
From http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
"There is no guarantee that every call to the Set method will release a thread. If two calls are too close together, so that the second call occurs before a thread has been released, only one thread is released. It is as if the second call did not happen. Also, if Set is called when there are no threads waiting and the AutoResetEvent is already signaled, the call has no effect."
One idea would be to use a separate event for each thread as the supplied link illustrates.
This is not a real consumer / producer pattern implementation.
e.Set() will release only ONE thread that is waiting using e.WaitOne()
So, when you write:
e.Set();
e.WaitOne();
On the producer thread, you are actually not enabling the consumer thread to get the signal
Try the following:
static void Producer()
{
while (true)
{
Thread.Sleep(1000);
Console.WriteLine("Produced " + num++);
e.Set();
}
}
static void Consumer()
{
while (true)
{
e.WaitOne();
Console.WriteLine("Consumed " + num);
}
}
If your okay with your consumer and producer thread running wild you can simplify your program by removing some of the sets and waitones:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Threaddd
{
internal class Program
{
private static int num = 0;
private static EventWaitHandle e = new AutoResetEvent(false);
private static object o = new object();
private static void Main(string[] args)
{
new Thread(Consumer).Start();
new Thread(Producer).Start();
}
private static void Producer()
{
while (true)
{
if (num == 0)
{
num++;
Console.WriteLine("Produced " + num);
Thread.Sleep(1000);
e.Set();
}
}
}
private static void Consumer()
{
while (true)
{
if (num == 1)
{
Console.WriteLine("Consumed " + num);
Thread.Sleep(1000);
num--;
e.WaitOne();
}
}
}
}
}
If that is not an option both your producer and consumer(s) must have their own events.
To keep num between 0 and 1 you can use the following pattern and lose the if statements:
class Program
{
static volatile int num = 0;
// Initialized set to ensure that the producer goes first.
static EventWaitHandle consumed = new AutoResetEvent(true);
// Initialized not set to ensure consumer waits until first producer run.
static EventWaitHandle produced = new AutoResetEvent(false);
static void Main(string[] args)
{
new Thread(Consumer).Start();
new Thread(Producer).Start();
}
static void Producer()
{
while (true)
{
consumed.WaitOne();
num++;
Console.WriteLine("Produced " + num);
Thread.Sleep(1000);
produced.Set();
}
}
static void Consumer()
{
while (true)
{
produced.WaitOne();
Console.WriteLine("Consumed " + num);
Thread.Sleep(1000);
num--;
consumed.Set();
}
}
}
It is worth pointing out that normally there is some kind of queue between the producer and the consumer so that the producer can create more than one item between each run of the consumer. The way I have written the above there is little point having the consumer and producer on separate threads as they will not be able to run at the same time.

Creating a deadlock

I have some code that looks like the below. Does this create a deadlock?
private readonly object objectLock = new object();
public void MethodA()
{
lock(objectLock)
{
MethodB();
}
}
public void MethodB()
{
lock(objectLock)
{
//do something
}
}
UPDATE: There will 2 threads running
No - but this would be:
private readonly object objectLockA = new object();
private readonly object objectLockB = new object();
public void MethodA()
{
lock(objectLockA)
{
lock(objectLockB)
{
//...
}
}
}
public void MethodB()
{
lock(objectLockB)
{
lock(objectLockA)
{
//do something
}
}
}
If you call both Methods in parallel (from 2 different threads) then you would get a deadlock...
No its not a deadlock. Its the same thread locking on the same synchronization object. A thread can take nested locks. It just needs to release it equal no. of times.
No, you'd need two lock objects to enable a deadlock.
If this is the only mutex involved, it isn't. The same thread can lock the same mutex multiple times, as long it unlocks it equal number of times.
Calling MethodA produces the following sequence of operations on the same thread:
Lock objectLock.
Call MethodB.
Lock objectLock.
Unlock objectLock.
Exit MethodB.
Unlock objectLock.
So, objectLock is locked twice and unlocaked twice, but there is no deadlock:
If another thread tries to call MethodA it will simply block on the first lock but will not deadlock.
It if calls MethodB, the same would happen.
And if first thread call MethodB and then other thread calls MethodA, again "normal" blocking would take place but not a deadlock.
If you copy paste the following lines, compile and run see that "never called" is not printed in the console.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace deadlocktest
{
class Program
{
static object object1 = new object();
static object object2 = new object();
public static void FunctionOne()
{
lock (object1)
{
Console.WriteLine("FunctionOne called 1");
Thread.Sleep(1000);
lock (object2)
{
Console.WriteLine("FunctionOne called 2, never called");
}
}
}
public static void FunctionTwo()
{
lock (object2)
{
Console.WriteLine("FunctionTwo called 1");
Thread.Sleep(1000);
lock (object1)
{
Console.WriteLine("FunctionTwo called 2, never called");
}
}
}
static void Main(string[] args)
{
Thread thread1 = new Thread(FunctionOne);
Thread thread2 = new Thread(FunctionTwo);
thread1.Start();
thread2.Start();
int i = 0;
while (i < 9)
{
Console.WriteLine("How bad thread!");
i++;
}
thread1.Join();
thread2.Join();
Console.ReadLine();
}
}
}

Categories

Resources