Open a mutex shared with a service - c#

I have a service that creates a thread with a loop that should run until the mutex is signalled by another process. I have the following in my service code
private readonly Mutex _applicationRunning = new Mutex(false, #"Global\HsteMaintenanceRunning");
protected override void OnStart(string[] args)
{
new Thread(x => StartRunningThread()).Start();
}
internal void StartRunningThread()
{
while (_applicationRunning.WaitOne(1000))
{
FileTidyUp.DeleteExpiredFile();
_applicationRunning.ReleaseMutex();
Thread.Sleep(1000);
}
}
Now I have a console application that should claim the mutex and force the while loop to be exited
var applicationRunning = Mutex.OpenExisting(#"Global\HsteMaintenanceRunning");
if (applicationRunning.WaitOne(15000))
{
Console.Write("Stopping");
applicationRunning.ReleaseMutex();
Thread.Sleep(10000);
}
When the console application tries to open the mutex I get the error "The wait completed due to an abandoned mutex." Whats wrong here?

I recommend that you use the Service's built-in stop signal rather than a mutex. The mutex class is more appropriate for managing exclusive access to a shared resource, which is not what's going on here. You could also use a system event but since services already have a built-in mechanism for signaling when they're stopping, why not use it?
Your service's code would look like this:
bool _stopping = false;
Thread _backgroundThread;
protected override void OnStart(string[] args)
{
_backgroundThread = new Thread(x => StartRunningThread());
_backgroundThread.Start();
}
protected override void OnStop()
{
_stopping = true;
_backgroundThread.Join(); // wait for background thread to exit
}
internal void StartRunningThread()
{
while (!stopping)
{
FileTidyUp.DeleteExpiredFile();
Thread.Sleep(1000);
}
}
Then, your console application would need to use the framework's ServiceController class to send the shut down message to your service:
using System.ServiceProcess;
...
using (var controller = new ServiceController("myservicename")) {
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(15.0));
}

Related

C# Start and Stop same thread using 2 different buttons

I have created a simple form home and there is another file Mouse_Tracking.cs.
Mouse_Tracking.cs class is a thread class. I want to start and stop that thread using two different button click in home form.
How can I do this ?
Main form:
namespace computers
{
public partial class home : Form
{
public home()
{
InitializeComponent();
}
private void btn_start_Click(object sender, EventArgs e)
{
var mst = new Mouse_Tracking();
Thread thread1 = new Thread(new ThreadStart(mst.run));
thread1.Start();
}
private void btn_stop_Click(object sender, EventArgs e)
{
//Here I want to stop "thread1"
}
}
}
Computers class:
namespace computers
{
public class Mouse_Tracking
{
public void run()
{
// Some method goes here
}
}
You shouldn't kill threads from the outside. Instead, you should gently ask your thread to terminate, and in your thread you should respond to that request and return from the thread procedure.
You could use an event for that. E.g. add the following to your form class:
AutoResetEvent evtThreadShouldStop = new AutoResetEvent();
In your run method, check if the svtThreadShouldStop event is set every 0.1-1 seconds, if it’s set, return from the thread function, e.g. if( evtThreadShouldStop.WaitOne( 0 ) ) return;
And in your btn_stop_Click call evtThreadShouldStop.Set();
P.S. It’s rarely a good decision to create your own thread: creating and destroying threads is expensive. The runtime already has the thread pool you can use for your own background processing. To post your background task to a pool thread instead use e.g. ThreadPool.QueueUserWorkItem method. You can use same technique with AutoResetEvent to request task termination.
P.P.S. The name of the Mouse_Tracking class suggest you're trying to interact with mouse from the background thread? You can't do that: you can only interact with the GUI including mouse and keyboard from the GUI thread.
Here is an example of what Soonts has suggested. It's quite old-style solution but it's simple and will work fine. But there is a number of other approaches. You can use BackgroundWorker or TPL (Task class), each of which have own thread stop mechanisms.
And I believe that it's ok to create own thread without using existing thread pool if you don't need to do it too often.
public class Mouse_Tracking
{
private ManualResetEvent _stopEvent = new ManualResetEvent(false);
public void stop()
{
_stopEvent.Set();
}
public void run()
{
while (true)
{
if (_stopEvent.WaitOne(0))
{
//Console.WriteLine("stop");
// handle stop
return;
}
//Console.WriteLine("action!");
// some actions
Thread.Sleep(1000);
}
}
}
Sometimes its quite difficult to maintain the thread. You can achieve it by using BackgroundWorker class. You will get complete demonstration on how to use it is here Stop Watch Using Background Worker. I hope it will be useful.
You could use a class like this for controlling your thread(s):
class ThreadController {
private Thread _thread;
public void Start(ThreadStart start) {
if (_thread == null || !_thread.IsAlive) {
_thread = new Thread(start);
_thread.Start();
}
}
public void Stop() {
if (_thread != null && _thread.IsAlive) {
_thread.Interrupt(); // Use _thread.Abort() instead, if your thread does not wait for events.
_thread = null;
}
}
}
Then use:
public partial class home : Form
{
public home()
{
InitializeComponent();
_thread = new ThreadController();
}
private readonly ThreadController _thread;
private void btn_start_Click(object sender, EventArgs e)
{
var mst = new Mouse_Tracking();
_thread.Start(mst.run);
}
private void btn_stop_Click(object sender, EventArgs e)
{
_thread.Stop();
}
}

Is there a way to get a notification, when the main thread stops in C#

I'm writing an application that uses a separate thread for logging.
I'd like to stop the separate thread when the main thread stops. However I'm unable to figure out when to stop the logger thread exactly as I don't know when the main thread stops. Is there a mechanism in C# that would send a notification when the main thread stops? (Or can you think about another solution to my problem?)
// This class automatically applies on each call of every method of Main() function
public class CommandLoggingAdvice : IMethodInterceptor
{
private static ProducerConsumerClass LoggingQueue = ProducerConsumerClass.Instance;
LoggingQueue.AddTask("Logging message on call of *method*");
}
public sealed class ProducerConsumerClass
{
// here Iget an instance of log4net
private ILog _Logger = null;
protected ILog Logger
{
_Logger = LogManager.GetLogger("Logger1");
}
private BlockingCollection<string> tasks = new BlockingCollection<string>();
private static volatile ProducerConsumerClass _instance;
Thread worker;
private Thread mainthread;
private ProducerConsumerClass()
{
mainthread = Thread.CurrentThread;
worker = new Thread(Work);
worker.Name = "Queue thread";
worker.IsBackground = false;
worker.Start(mainthread);
}
public static ProducerConsumerClass Instance
{
get
{
if (_instance == null)
{
_instance = new ProducerConsumerClass();
}
}
}
public void AddTask(string task)
{
tasks.Add(task);
}
void Work(object mainthread)
{
Thread ma = (Thread) mainthread;
if(ma.ThreadState != ThreadState.Stopped)
{
tasks.CompleteAdding();
}
while (true)
{
string task = null;
if (!tasks.IsCompleted)
{
task = tasks.Take();
Logger1.Info(task);
}
else
{
return;
}
}
}
}
If BlockingCollection is empty and application is still working, loop calls one more Take() and result: logger thread is paused now. So when main thread.Threadstate == Stopped, i need to kill logger thread
More info about issue were added in comments
You already have code in the thread that exits if the BlockingCollection is empty and marked as completed. Your loop checks for IsCompleted and exits.
What you need is some way for the main thread to call CompleteAdding on the collection. I would recommend a public method in your ProducerConsumerClass:
public void AllDone()
{
tasks.CompleteAdding();
}
So the main thread can call AllDone when it's done processing. Your thread will then empty the queue and exit.
By the way, a more concise way to write your logging loop is:
foreach (string task in tasks.GetConsumingEnumerable())
{
Logger1.Info(task);
}
This also makes it easier to add cancellation support in the future.

Preventing threads from processing further once call to stop is being made

I have a windows service which will start and stop the execution of some process that is being done with the held of Threads.
I have two classes as follows:
public class PerformTask
{
Thread _thread = null;
public void StartTask()
{
_thread = new Thread(new ThreadStart(DoSomeWork));
_thread.Start();
}
public void DoSomeWork()
{
// Do Some Work
_thread = null;
}
public void Abort()
{
if (_thread != null)
{
try
{
_thread.Abort();
}
catch (ThreadAbortException) {}
}
}
}
public class Engine
{
List<PerformTask> _task = new List<PerformTask>();
public void Start()
{
var task = new PerformTask();
_task.Add(task);
// Add task to the timed action queue
_actionQueue.Add(s => task.StartTask(), TimeSpan.FromSeconds(10));
}
public void Stop()
{
_task.ForEach(task => task.Abort());
_task.Clear();
_actionQueue.Stop();
_actionQueue.Clear();
}
}
The _actionQueue is a custom defined source code developed to perform a specified action at a recurring time interval specified. All the actions are kept in queue and invoked at the specified time interval.
Now, the Windows service's OnStart and OnStop method would call Engine class' Start and Stop method respectively.
What I want is when the windows service is stopped, all the threads that are running should stop their processing/execution.
But, what is happening here is as new thread instance is being created in I have a windows service which will start and stop the execution of some process that is being done with the held of Threads.
I have two classes as follows:
public class PerformTask
{
Thread _thread = null;
public void StartTask()
{
_thread = new Thread(new ThreadStart(DoSomeWork));
_thread.Start();
}
public void DoSomeWork()
{
// Do Some Work
_thread = null;
}
public void Abort()
{
if (_thread != null)
{
try
{
_thread.Abort();
}
catch (ThreadAbortException) {}
}
}
}
public class Engine
{
List<PerformTask> _task = new List<PerformTask>();
ActionQueue _actionQueue = new ActionQueue();
public void Start()
{
foreach(.....)
{
var task = new PerformTask();
_task.Add(task);
// Add task to the timed action queue
_actionQueue.Add(s => task.StartTask(), TimeSpan.FromSeconds(10));
}
_actionQueue.Start();
}
public void Stop()
{
_task.ForEach(task => task.Abort());
_task.Clear();
_actionQueue.Stop();
_actionQueue.Clear();
}
}
The ActionQueue is a custom defined source code developed to perform a specified action at a recurring time interval specified. All the actions are kept in queue and invoked at the specified time interval.
Now, the Windows service's OnStart and OnStop method would call Engine class' Start and Stop method respectively.
What I want is when the windows service is stopped, all the threads that are running should stop their processing/execution.
But, what is happening here is as new thread instance is being created in StartTask method, when I call the
_task.ForEach(task => task.Abort())
I do not have the correct instance of Thread, that is all the instance of
_thread = new Thread(....);
is not being accessed, as there would a multiple queues for the same PerformTask class.
Note: I cannot make changes to the ActionQueue.
Is Abort method a correct way of stopping the threads?
How can I stop all the threads (including all the instances of Thread class created by the source code)?
Usually you'd create a WaitHandle (a ManualResetEvent for example) like that:
ManualResetEvent stopAllThreads = new ManualResetEvent(false);
So the event is "not set". Change the loops in your thread method so that they loop until all work is done or the manual reset event is set.
while (!stopAllThreads.WaitOne(50))
or similar.
Then, in the service's OnStop method, you simply set the event (don't forget to reset it again in OnStart, otherwise the threads will not run again when the service is restarted):
stopAllThreads.Set();
and wait for all the threads to finish.
Actually, aborting threads is not a good way to stop threads - you should always go for something like the above.

Windows Service + read from database

I am new To windows service. I need a windows service that reads an entry from a table from database. I have a CONSOLE APP where I add new project WINDOWS SERVICE. I already have a method that access the database, and other methods. I can put a thread on start that reads the database. Where do I put the thread? ( how can I do that). Where on WINDOWS SERVICE I add those methods? I have the Windows Service like this:
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
do
{
thread.start();
bool variab = readFromDatabase (Database table);
}
}
protected override void OnStop()
{
}
I suggest that you create a class in which you do everything you need and create in in the service:
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
YourClass cl = new YourClass();
cl.DoWhatYouNeed(...);
}
protected override void OnStop()
{
}
This gives you opportunity to run and test your class separate from service, maybe during debug release.
With windows services usually a method is created to execute the main loop of the service, in a separated thread. Otherwise the service could become unresponsive. For example, you can have a method called MainLoop to execute the service logic. Use the OnStart method only to do the initializing tasks, such as read configuration values or start the threads of the service. And use the OnStop to executing cleaning tasks, stopping threads, etc...
Thread _workerThread;
bool _shouldStop;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try{
_workerThread = new Thread(new ThreadStart(MainLoop));
_shouldStop = false;
_workerThread.Start();
}
catch{}
}
private void MainLoop()
{
while (!_shouldStop)
{
try{
//your logic here
}
catch{}
}
}
protected override void OnStop()
{
_shouldStop = true;
}
You must put your code or class, which contain data access logic in OnStart method

WPF mutex for single app instance not working

I'm trying to use the mutex method for only allowing one instance of my app to run. That is - I only want a max of one instance for all users on a machine. I've read through the various other threads on this issue and the solution seems straightforward enough but in testing I can't get my second instance to not run. Here is my code...
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
// check that there is only one instance of the control panel running...
bool createdNew = true;
using (Mutex instanceMutex = new Mutex(true, #"Global\ControlPanel", out createdNew))
{
if (!createdNew)
{
Application.Current.Shutdown();
return;
}
}
base.OnStartup(e);
}
}
You're also disposing the mutex in the same method, so the mutex only lives for the duration of the method. Store the mutex in a static field, and keep it alive for the duration of your application.
Here is my new code which has the answer provided by #Willem van Rumpt (and #OJ)...
public partial class App : Application
{
private Mutex _instanceMutex = null;
protected override void OnStartup(StartupEventArgs e)
{
// check that there is only one instance of the control panel running...
bool createdNew;
_instanceMutex = new Mutex(true, #"Global\ControlPanel", out createdNew);
if (!createdNew)
{
_instanceMutex = null;
Application.Current.Shutdown();
return;
}
base.OnStartup(e);
}
protected override void OnExit(ExitEventArgs e)
{
if(_instanceMutex != null)
_instanceMutex.ReleaseMutex();
base.OnExit(e);
}
}
You're destroying the Mutex immediately after you've created it and tested it. You need to keep the Mutex reference alive for lifetime of your application.
Make the Mutex a member/field of your Application class.
Release the mutex when your application shuts down.
As extension sample:
public static class Extension
{
private static Mutex mutex;
public static bool IsOneTimeLaunch(this Application application, string uniqueName = null)
{
var applicationName = Path.GetFileName(Assembly.GetEntryAssembly().GetName().Name);
uniqueName = uniqueName ?? string.Format("{0}_{1}_{2}",
Environment.MachineName,
Environment.UserName,
applicationName);
application.Exit += (sender, e) => mutex.Dispose();
bool isOneTimeLaunch;
mutex = new Mutex(true, uniqueName, out isOneTimeLaunch);
return isOneTimeLaunch;
}
}
App Class:
protected override void OnStartup(StartupEventArgs e)
{
if (this.IsOneTimeLaunch())
{
base.OnStartup(e);
}
else
{
this.Shutdown();
}
}
I can suggest a much cleaner approach that also introduce the useful concept of overriding the Main method in WPF application. Also, if using your solution you take a look at the task manager, you will notice that the new instance actually reach the execution state (you can see a new process created in the list of task) and then suddenly close. The approach proposed in the post that follows will avoid this drawback too.
http://blog.clauskonrad.net/2011/04/wpf-how-to-make-your-application-single.html
I was told to implement this mutex approach on an already developed WPF application that we had. The work around to the problem with using override of the OnStart() that I found was in
App.g.cs
This file is located in
obj\x86\debug\
and contains the main() function, so you just simply put this piece of code in your main function.
bool isOnlyInstance = false;
Mutex m = new Mutex(true, #"WpfSingleInstanceApplication", out isOnlyInstance);
if (!isOnlyInstance)
{
MessageBox.Show("Another Instance of the application is already running.",
"Alert",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
return;
}
GC.KeepAlive(m);
but for this you need to keep the BUILD ACTION of your app.xaml set to ApplicationDefinition
NOTE: This might not be the best way, since I'm a beginner. (please tell me if there's something I should change)
I did this from this link just add the given class and a single line in you App.Xaml.cs
http://wpfsingleinstance.codeplex.com/
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
WpfSingleInstance.Make(); //added this is the function of that class
base.OnStartup(e);
}
}

Categories

Resources