Implementing a waiting routine inside a timer_elapsed event - c#

I have a kept a polling timer to check if a process is running or not. I have the following simple code for this:
bool alreadyChecked = false; //check if the wait to check the second time is already over
**Timer_elapsed event**
Process sampleProcess[] = Process.GetProcessesByName("notepad");
if(sampleProcess.length > 0)
{
//Process is running
return;
}
else
{
//Process is not running, so do the following
//Wait for some time and check again (set alreadyChecked = true when the wait is over)
if (alreadyChecked){
//Run the process}
else{
//The process has started running while we were waiting
return;}
}
I am not able to implement the waiting code inside the event, so that it can wait and then fire the event again. (Even if we implement the wait time, the Timer_elapsed event will be fired by timer again while we were waiting.)
Any suggestions?

You should create a separate thread and use the sleep method, using a BackgroundWorker is the best option. You can also use a timer thread.
**BackgroundWorker_DoWork event**
int nTrials = 0; // this method will help you pick any number of trials before launching the applicaion
bool isRunning = false;
while((isRunning = Process.GetProcessesByName("notepad") == 0) || nTrials < 2)
{
Thread.Sleep(1000); // w8 1 second before queriying the process name
nTrials++;
}
if ( isRunning ) RunProcess();
Don't use the sleep method on your main thread or your application will stop handling messages for the sleep time.

Related

How to stop looper execution?

I have a looper thread that is running always and pull tasks from queue in order to execute them.
There is a main looper method
public void Start()
{
m_looperThread = new Thread(() =>
{
while (true)
{
//Dequeue use lock inside
TASK_TYPE task = m_taskList.GetAndRemoveFirst();
if (task == null || !m_isThreadRunning)
{
break;
}
task.Execute();
FinishedTask(task);
}
}
)
{
IsBackground = true
};
m_looperThread.Start();
}
Now if I need to close an application, user need to click red cross and before closing I need to abort all looper tasks.
How I do it
public void Abort()
{
Put(default(TASK_TYPE));
m_isThreadRunning = false;
if (m_looperThread != null)
{
m_looperThread.Join();
}
m_taskList.Clear();
}
So, first of all I put a null item and additional I set m_isThreadRunning value to false because in looper method I am checking this values in order to stop it. Then I call .Join() to make sure that I finished this thread and clear task list. Now I know exactly that all tasks were aborted, threads were joined and all is fine.
But issue here in this line
task.Execute();
What is the issue - when task run and user need to close the application I can't .Join the looper thread before task finish the job (it could be 1 minute). And finally it is looks like application in stuck.
So, question is - how correctly .join the thread and give to user opportunity to close the application?

How to run a while loop just once even when the condition stays true for more time than required to complete the loop

I have a application where I'm checking if the signal read from a PLC is true or false, if its true - it does a set of calculations and if its false, it waits for the signal. I'm using a while loop to do this. But the problem is that the true state stays on for 1000ms, and the loop completes in less than 100ms, so it goes back up again and since the state is true it proesses it again. Hence for 1 signal that I receive from PLC, the loop runs for about 9-10 times. I tried adding thread.sleep but still it processes it more than once. I want the loop to run once when the state is true and then wait for it to get true again.
Here is the code:
bool isRunning = true;
private void WorkThreadFunction()
{
while (isRunning)
{
if (ethernetIPforSLCMicroCom1.Read("B3:254/1") == "True")
{
stopWatch = Stopwatch.StartNew();
int isTriggered;
Int32.TryParse(trigger, out isTriggered);
timer1.Start();
Thread.Sleep(10);
serialcheck();
System.GC.Collect();
}
}
I work on a program reading signal from GPIO pin and your problem is quite similar to mine, aka preventing a single on signal from being processed multiple times. My solution to this is I try to ensure that the signal is off first before I go to check whether the signal is on again.
while (isRunning)
{
var signal = ethernetIPforSLCMicroCom1.Read("B3:254/1");
if (signal == "True")
{
//do your stuff
}
while (signal == "True")
signal = ethernetIPforSLCMicroCom1.Read("B3:254/1");
}
The inner loop will wait for the signal to turn something other than "True" before it continues any other execution.
In order to wait for it to be true again you need to keep track of whether it has been false.
bool isRunning = true;
bool signalHasBeenFalse = true;
private void WorkThreadFunction()
{
while (isRunning)
{
if (ethernetIPforSLCMicroCom1.Read("B3:254/1") == "True" && hasBeenFalse )
{
signalHasBeenFalse = false;
stopWatch = Stopwatch.StartNew();
int isTriggered;
Int32.TryParse(trigger, out isTriggered);
timer1.Start();
Thread.Sleep(10);
serialcheck();
System.GC.Collect();
}
if ( ethernetIPforSLCMicroCom1.Read("B3:254/1") != "True" )
{
signalHasBeenFalse = true;
}
}
}
If I am reading it correctly you just need to put a break; in where your condition is met in the while loop.
I made an example here: https://dotnetfiddle.net/FsGryD
I would also add that you might consider if using SpinWait.SpinUntil(<boolean_condition>) might be a better option. (https://msdn.microsoft.com/en-us/library/system.threading.spinwait(v=vs.110).aspx).
I have used that previously on multi threading / IO waiting functions to wait for signals from devices.

Looping a Background Worker Task

I have some code inside a background worker DoWork event which check if a process is running or not. The code in the DoWork does the following:
-> If the process is not running, check again twice
-> If the process is running, check if it is responding
-> If the process is running and respoding, do nothing
-> If the process is running and not responding, restart the process
void bgworker_DoWork(object sender, DoWorkEventArgs e)
{
int numberTrials = 0;
bool isNotRunning = false;
while (isNotRunning = (someProcess.Length == 0) && numberTrials < 3)
{
Debug.WriteLine(String.Format("numTrial = {0}", numberTrials.ToString()));
Thread.Sleep(3000);
++numberTrials;
}
if (isNotRunning)
{
Debug.WriteLine("Start Task");
someProcess.Start();
}
else
{
if(!someProcess.IsKioskResponding)
{
Debug.WriteLine("Kill Task");
}
}
}
The above thing runs fine but I have to loop the above DoWork task for every 3 minutes. Would it be a good thing to keep the above looping task in a timer that has an interval of 3 minutes? (In that way I would have to take care of Thread.Sleep x numberTrials not to exceed the Timer's interval). Any thoughts on this?
Have you also had a look at the Process.WaitForExit Method
It is explained with an example here: process restart loop

Gracefully shutdown a thread

In an application I'm developing, I have a main form that simply sits there and displays log data, and a worker thread that autonomously does the work in a loop.
MyWorker worker = new MyWorker();
MainForm mainForm = new MainForm();
// Subscribe form to log event so log data gets displayed
worker.Log += mainForm.Log;
// Start the worker thread's MainLoop
new Thread(new ThreadStart(worker.MainLoop)).Start();
// Show the form (blocking)
Application.Run(mainForm);
// If we end up here, the form has been closed and the worker has to stop running
worker.Running = false;
As you can see, whenever the form is closed, the worker thread should be stopped. The worker looks like this:
public class MyWorker
{
public String Running { get; set; }
public MyWorker()
{
Running = true;
}
public void MainLoop()
{
while (Running)
{
DoExtensiveWork1();
if (!Running) return;
DoExtensiveWork2();
if (!Running) return;
DoExtensiveWork3();
if (!Running) return;
DoExtensiveWork4();
if (!Running) return;
DoExtensiveWork5();
if (!Running) return;
// We have to wait fifteen minutes (900 seconds)
// before another "run" can be processed
for (int i = 0; i < 900; i++)
{
Thread.Sleep(1000);
if (!Running) return;
}
}
}
}
As you can see, I want the thread to be able to stop when switching between successive work operations, but not when within an operation. When an operation (DoExtensiveWorkN) has finished, its status and results are persisted do disk or database, so quitting while an operation is in progress (by, for example, Thread.Abort) is not an option.
However, I find this code I've just written repulsive to look at, especially the "wait loop" which sleeps for one second 900 times, to prevent the thread from idling for 15 minutes before detecting Running has been set to false.
I'd rather be able to throw some kind of event to stop the main loop as soon as it's finished a piece of work.
Can anyone point me in the right direction how to do this, or if a total rewrite is required because I totally misunderstood threading, show me somewhere where those principles are explained?
You can tidy up both the running of the individual tasks and the 15 min wait loop considerably.
I'd suggest perhaps using something like this:
public class MyWorker
{
private readonly ManualResetEvent _stopEvent = new ManualResetEvent(false);
private readonly Action[] _workUnits;
private bool Running
{
get { return !_stopEvent.WaitOne(0); }
}
public MyWorker()
{
_workUnits = new Action[]
{
DoExtensiveWork1,
DoExtensiveWork2,
DoExtensiveWork3,
DoExtensiveWork4,
DoExtensiveWork5
};
}
public void Stop()
{
_stopEvent.Set();
}
public void MainLoop()
{
while (Running)
{
foreach (var workUnit in _workUnits)
{
workUnit();
if (!Running) return;
}
// We have to wait fifteen minutes (900 seconds)
// before another "run" can be processed
if (_stopEvent.WaitOne(900000)) return;
}
}
}
Then to stop the process at the next appropriate point:
Worker.Stop();
I would suggest using System.Timers.Timer.
You can do your work with the running thing and rather than using the sleep you can just set the timer to go off again in 15 minutes.
If you want to stop it early then call some kind of abort method (similar to setting your Running=true variable) that will stop the timer.
It should be noted that each time the timer event fires it will start up a new thread so you dont' need to worry about killing background threads. Your thread finishes its run of processing, sets the timer to run in 15 minutes and then the thread finishes naturally. If you abort during a wait then you just get rid of the timer and no more cleanup needed. If you abort during a run then you let the run finish and at the end it checks a flag and doesn't start the timer again and then the thread finishes.
For the timer you'll want to set the timer to start manually at the end of the process. The alternative is to have the timer ticking every 15 minutes but that would mean that if your processing took 10 minutes then it owuld only be 5 minutes before the next run. And if it took more than 15 minutes you may be in trouble. Also restarting the timer manually guarantees that the processing shouldn't restart while another is running.

how to stop current process of C# application and start another function

I am explaining my scenario, i have a function which print 1 to 10000 while printing i have to stop the process and let user know the current i value and if user presses enter it should continue again.
i am using
if ((Console.KeyAvailable) && (Console.ReadKey(true).Key == ConsoleKey.Escape))
but it doesn,t work, to complicate my task i am using threads, even if i manage to break this thread, child thread starts executing, i just want to stop the entire execution process for a moment and execute another function.
Check out the BackgroundWorker class, specifically, how to implement cancellation.
You'll basically need to check inside the loop if a cancellation is pending. If it is, then exit the loop.
If your using Threads. You can use this kind of code..
// Start
thread = new Thread(new ThreadStart(YourCommand));
thread.Start();
// Pause
if (thread != null)
{
thread.Suspend();
}
//Continue
if (thread != null)
{
thread.Resume();
}
//Alive
if (thread != null)
{
if (thread.IsAlive)
{
thread.Abort();
}
}
Or you can use timer....

Categories

Resources