Continuously check if condition in different thread - c#

I have two datetimes. One is current and another is the datetime when race starts.Now I want check this Minutes difference continuously in background thread(I dont know about thread). And when it meets the if(remainingMinutes <=4) I want to update the UI. How to implement this with thread in background?
public RelayCommand OpenSetBets
{
get { return _setBets ?? (_setBets = new RelayCommand(ExecuteSetBets, CanExecuteSetBets)); }
}
private void ExecuteSetBets()
{
_navigation.NavigationToSetBetsDialogue();
}
private bool CanExecuteSetBets()
{
// Thread t = new Thread(newthread);
double? remainingMinutes = null;
if (UK_RaceDetail.Count() != 0)
{
//t.Start();
DateTime CurrentUTCtime = DateTime.UtcNow;
DateTime NextRaceTime = UK_RaceDetail[0].One.Time;
remainingMinutes = NextRaceTime.Subtract(CurrentUTCtime).TotalMinutes;
}
if (remainingMinutes <= 4)
{
return true;
}
else
{
return false;
}
}
Updated Code.
I want to enable button if race is going to start in next 4 minutes.

If you only want to use your background task to monitor the date/time, I recommend you not to create a new Thread.
For WPF, instead of thread, you can try to use DispatcherTimer object with its Tick event
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += dispatcherTimer_Tick;
For WinForms, you can use Timer object with its Tick event
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Tick += timer_Tick;
This way, you are rather saved from more complex solution using Thread or ThreadPool
Edit: to use Task.Delay, as some prefer this rather "cleaner" way, see the comment by Mr. Aron

You can use Task.Run like,
System.Threading.Tasks.Task.Run(async () =>
{
//starts running in threadpool parallelly
while (!CanExecuteSetBets())
{
await Task.Delay(500); //wait 500 milliseconds after every check
}
DoYourWork(); //trigger your work here
}).ConfigureAwait(false);

Related

Should I use Thread.Sleep() to check if a process is still running?

As title says, I'm currently making a WPF application and I need to detect if an application is running and do something when it's closed. The way I'd thought of doing so is by running a separate Thread and checking every two seconds if the process is still running, something like this:
while(Process.GetProcessesByName(processName).Length != 0) {
Thread.Sleep(2000);
}
//Do something
Would this be a good solution, is there any other way of doing this?
Thanks
Would this be a good solution?
No, because it would waste an entire thread for nearly nothing.
Better use a timer, in a WPF application preferrably a DispatcherTimer:
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
timer.Tick += (s, e) =>
{
if (Process.GetProcessesByName(processName).Length > 0)
{
// ...
}
};
timer.Start();
If there would be a lengthy operation to be performed off the UI thread, you could use an async Tick event handler that awaits a Task (which would run on a thread pool thread in the background):
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
timer.Tick += async (s, e) =>
{
if (Process.GetProcessesByName(processName).Length > 0)
{
await Task.Run(() =>
{
// lengthy operation here which runs on a thread pool thread
});
// udate UI here
}
};
timer.Start();
Since you are already dealing with Processes, I would suggest just using it directly to determine if it has exited. You can use the Exited event handler for your code. So, for instance:
foreach (var process in Process.GetProcessesByName(processName))
{
process.Exited += new EventHandler(DoSomething);
}
…
public void DoSomething(object sender, System.EventArgs e)
{
// do something
}
This will call DoSomething when the process with that name ends.
You could use a System.Timers.Timer that performs the check every x seconds:
public sealed partial class Window1 : Window, IDisposable
{
private readonly System.Timers.Timer _timer = new System.Timers.Timer(TimeSpan.FromSeconds(2).TotalMilliseconds);
public Window1()
{
InitializeComponent();
_timer.Elapsed += _timer_Elapsed;
_timer.Start();
}
private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (Process.GetProcessesByName("processName...").Length == 0)
{
_timer.Stop();
_timer.Dispose();
//do something...
}
}
public void Dispose()
{
_timer.Dispose();
}
}
Unlike the Tick event of a DispatcherTimer, the Elapsed event of a Timer is always queued for execution on a thread pool thread.
From the docs:
If a System.Timers.Timer is used in a WPF application, it is worth noting that the System.Timers.Timer runs on a different thread than the user interface (UI) thread...Reasons for using a DispatcherTimer as opposed to a System.Timers.Timer are that the DispatcherTimer runs on the same thread as the Dispatcher and a DispatcherPriority can be set on the DispatcherTimer.

How to schedule async execution with different elapse times?

I have 2 sets of jobs that need to be performed separately and can't run parallel. The jobs involve web communication so async is used.
Currently, I have System.Windows.Forms.Timers set up to execute the batches with Task.Run(). To avoid the possible simultaneous execution, first I thought I can simply use a lock() {} inside the timers' Tick (I update the UI with countdown at ticks). Then realized that I need to .Wait() for the task to finish, otherwise it just exits the critical section.
Then I realized that all of this is running on the UI thread, so it's like those Elmer Fudd scenes where he points his rifle in one hole and the end comes out another pointing back at him.
Is there a simple nail-hammer approach to not block the UI thread while maintaining mutually excluded execution?
Here's a sample for one of the timers:
_timer = new Timer { Interval = 1000 };
_timer.Tick += (sender, args) =>
{
var timeSpan = _nextRun - DateTime.Now;
if (timeSpan.Seconds >= 0)
{
UpdateCountdownMessage(string.Format("{0:00}:{1:00}:{2:00} to next run.", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds));
}
else
{
lock (_runLock)
{
Task.Run(() => RunJobs(_batch1Jobs)).Wait();
}
}
};
To make it clearer, there is a 2nd timer, lets say it's called _timer2, that similarly updates a different countdown and runs _batch2Jobs when it reaches 0.
First you need to get rid of lock and switch to SemaphoreSlim
SemaphoreSlim _runLock = new SemaphoreSlim(1, 1);
Then you can use something like this
_timer.Tick += async (sender, args) =>
{
var timeSpan = _nextRun - DateTime.Now;
if (timeSpan.Seconds >= 0)
{
UpdateCountdownMessage(string.Format("{0:00}:{1:00}:{2:00} to next run.", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds));
}
else
{
_timer.Enabled = false;
try
{
await Task.Run(async () =>
{
await _runLock.WaitAsync();
try { RunJobs(_batch1Jobs); }
finally { _runLock.Release(); }
});
}
finally { _timer.Enabled = true; }
}
};
Please note that you should never use lock or Task.Wait on the UI thread for a long running tasks. The UI code should use only async/await constructs.
You should use tasks:
Task T1 = Task.Factory.StartNew(() => {/*do work */});
Task T2 = T1.ContinueWith((antecedent) => {/*do work 2*/});

How I can waiting some time in c# (windows service)

I created windows service on C#.
For now I have methods for scanning DB.
I need call this method two times per minute. Actually I don't know method for waiting in windows service.
I tried Thread.Sleep... but nothing happened.
Please help me with this problem.
private int wait;
protected void Start()
{
wait = 1000;
while (true)
{
if (wait < 30000)
wait += wait;
//implement logic for waiting
Video video = new Video();
video.FindFileForConvert();
if (video.Path != null)
{
Console.WriteLine("video != null. video path = {0}", video.Path);
video.BeginConvertation();
video.DeleteOriginFile();
wait = 1000;
}
}
}
You should use System.Threading.Timer for the same. Since Thread.sleep is not a good practice atleast in some cases.
You may use Timer
public static int Main() {
/* Adds the event and the event handler for the method that will
process the timer event to the timer. */
myTimer.Tick += new EventHandler(TimerEventProcessor);
// Sets the timer interval to 5 seconds.
myTimer.Interval = 5000;
myTimer.Start();
// Runs the timer, and raises the event.
while(exitFlag == false) {
// Processes all the events in the queue.
Application.DoEvents();
}
return 0;
}
I may be mistaken, but I think that this code will help you resolve your problem. DispatcherTimer
DispatcherTimer dispathcerTimer = new DispatcherTimer();
dispathcerTimer.Interval = TimeSpan.FromMinutes(2);
dispathcerTimer.Tick += dispathcerTimer_Tick;
dispathcerTimer.Start();
void dispatcherTime_Tick(object sender, object e)
{
//function, which needs to be invoked every two minutes.
}

How to invoke a UI method from another thread

Playing round with Timers.
Context: a winforms with two labels.
I would like to see how System.Timers.Timer works so I've not used the Forms timer.
I understand that the form and myTimer will now be running in different threads.
Is there an easy way to represent the elapsed time on lblValue in the following form?
I've looked here on MSDN but is there an easier way !
Here's the winforms code:
using System.Timers;
namespace Ariport_Parking
{
public partial class AirportParking : Form
{
//instance variables of the form
System.Timers.Timer myTimer;
int ElapsedCounter = 0;
int MaxTime = 5000;
int elapsedTime = 0;
static int tickLength = 100;
public AirportParking()
{
InitializeComponent();
keepingTime();
lblValue.Text = "hello";
}
//method for keeping time
public void keepingTime() {
myTimer = new System.Timers.Timer(tickLength);
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
myTimer.AutoReset = true;
myTimer.Enabled = true;
myTimer.Start();
}
void myTimer_Elapsed(Object myObject,EventArgs myEventArgs){
myTimer.Stop();
ElapsedCounter += 1;
elapsedTime += tickLength;
if (elapsedTime < MaxTime)
{
this.lblElapsedTime.Text = elapsedTime.ToString();
if (ElapsedCounter % 2 == 0)
this.lblValue.Text = "hello world";
else
this.lblValue.Text = "hello";
myTimer.Start();
}
else
{ myTimer.Start(); }
}
}
}
I guess your code is just a test so I won't discuss about what you do with your timer. The problem here is how to do something with an user interface control inside your timer callback.
Most of Control's methods and properties can be accessed only from the UI thread (in reality they can be accessed only from the thread where you created them but this is another story). This is because each thread has to have its own message loop (GetMessage() filters out messages by thread) then to do something with a Control you have to dispatch a message from your thread to the main thread. In .NET it is easy because every Control inherits a couple of methods for this purpose: Invoke/BeginInvoke/EndInvoke. To know if executing thread must call those methods you have the property InvokeRequired. Just change your code with this to make it works:
if (elapsedTime < MaxTime)
{
this.BeginInvoke(new MethodInvoker(delegate
{
this.lblElapsedTime.Text = elapsedTime.ToString();
if (ElapsedCounter % 2 == 0)
this.lblValue.Text = "hello world";
else
this.lblValue.Text = "hello";
}));
}
Please check MSDN for the list of methods you can call from any thread, just as reference you can always call Invalidate, BeginInvoke, EndInvoke, Invoke methods and to read InvokeRequired property. In general this is a common usage pattern (assuming this is an object derived from Control):
void DoStuff() {
// Has been called from a "wrong" thread?
if (InvokeRequired) {
// Dispatch to correct thread, use BeginInvoke if you don't need
// caller thread until operation completes
Invoke(new MethodInvoker(DoStuff));
} else {
// Do things
}
}
Note that current thread will block until UI thread completed method execution. This may be an issue if thread's timing is important (do not forget that UI thread may be busy or hung for a little). If you don't need method's return value you may simply replace Invoke with BeginInvoke, for WinForms you don't even need subsequent call to EndInvoke:
void DoStuff() {
if (InvokeRequired) {
BeginInvoke(new MethodInvoker(DoStuff));
} else {
// Do things
}
}
If you need return value then you have to deal with usual IAsyncResult interface.
How it works?
A GUI Windows application is based on the window procedure with its message loops. If you write an application in plain C you have something like this:
MSG message;
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
With these few lines of code your application wait for a message and then delivers the message to the window procedure. The window procedure is a big switch/case statement where you check the messages (WM_) you know and you process them somehow (you paint the window for WM_PAINT, you quit your application for WM_QUIT and so on).
Now imagine you have a working thread, how can you call your main thread? Simplest way is using this underlying structure to do the trick. I oversimplify the task but these are the steps:
Create a (thread-safe) queue of functions to invoke (some examples here on SO).
Post a custom message to the window procedure. If you make this queue a priority queue then you can even decide priority for these calls (for example a progress notification from a working thread may have a lower priority than an alarm notification).
In the window procedure (inside your switch/case statement) you understand that message then you can peek the function to call from the queue and to invoke it.
Both WPF and WinForms use this method to deliver (dispatch) a message from a thread to the UI thread. Take a look to this article on MSDN for more details about multiple threads and user interface, WinForms hides a lot of these details and you do not have to take care of them but you may take a look to understand how it works under the hood.
Personally when I work in an application that works with threads out of the UI one, I usually write this little snippet:
private void InvokeUI(Action a)
{
this.BeginInvoke(new MethodInvoker(a));
}
When I do an async call in a different thread I can always callback using:
InvokeUI(() => {
Label1.Text = "Super Cool";
});
Simple and clean.
As asked, here is my answer that checks for cross thread calls, synchronises variable updates, doesen't stop and start the timer and doesn't use the timer for counting elapsed time.
EDIT fixed BeginInvoke call. I've done the cross thread invoke using a generic Action, This allows the sender and eventargs to be passed. If these are unused (as they are here) it is more efficient to use MethodInvoker but I suspect the handling would need to be moved into a parameterless method.
public partial class AirportParking : Form
{
private Timer myTimer = new Timer(100);
private int elapsedCounter = 0;
private readonly DateTime startTime = DateTime.Now;
private const string EvenText = "hello";
private const string OddText = "hello world";
public AirportParking()
{
lblValue.Text = EvenText;
myTimer.Elapsed += MyTimerElapsed;
myTimer.AutoReset = true;
myTimer.Enabled = true;
myTimer.Start();
}
private void MyTimerElapsed(object sender,EventArgs myEventArgs)
{
If (lblValue.InvokeRequired)
{
var self = new Action<object, EventArgs>(MyTimerElapsed);
this.BeginInvoke(self, new [] {sender, myEventArgs});
return;
}
lock (this)
{
lblElapsedTime.Text = DateTime.Now.SubTract(startTime).ToString();
elapesedCounter++;
if(elapsedCounter % 2 == 0)
{
lblValue.Text = EvenText;
}
else
{
lblValue.Text = OddText;
}
}
}
}
First, in Windows Forms (and most frameworks), a control can only be accessed (unless documented as "thread safe") by the UI thread.
So this.lblElapsedTime.Text = ... in your callback is plain wrong. Take a look at Control.BeginInvoke.
Second, You should use System.DateTime and System.TimeSpan for your time computations.
Untested:
DateTime startTime = DateTime.Now;
void myTimer_Elapsed(...) {
TimeSpan elapsed = DateTime.Now - startTime;
this.lblElapsedTime.BeginInvoke(delegate() {
this.lblElapsedTime.Text = elapsed.ToString();
});
}
Ended up using the following. It's a combination of the suggestions given:
using System.Timers;
namespace Ariport_Parking
{
public partial class AirportParking : Form
{
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//instance variables of the form
System.Timers.Timer myTimer;
private const string EvenText = "hello";
private const string OddText = "hello world";
static int tickLength = 100;
static int elapsedCounter;
private int MaxTime = 5000;
private TimeSpan elapsedTime;
private readonly DateTime startTime = DateTime.Now;
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public AirportParking()
{
InitializeComponent();
lblValue.Text = EvenText;
keepingTime();
}
//method for keeping time
public void keepingTime() {
using (System.Timers.Timer myTimer = new System.Timers.Timer(tickLength))
{
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
myTimer.AutoReset = true;
myTimer.Enabled = true;
myTimer.Start();
}
}
private void myTimer_Elapsed(Object myObject,EventArgs myEventArgs){
elapsedCounter++;
elapsedTime = DateTime.Now.Subtract(startTime);
if (elapsedTime.TotalMilliseconds < MaxTime)
{
this.BeginInvoke(new MethodInvoker(delegate
{
this.lblElapsedTime.Text = elapsedTime.ToString();
if (elapsedCounter % 2 == 0)
this.lblValue.Text = EvenText;
else
this.lblValue.Text = OddText;
}));
}
else {myTimer.Stop();}
}
}
}

Synchronizing a timer to prevent overlap

I'm writing a Windows service that runs a variable length activity at intervals (a database scan and update). I need this task to run frequently, but the code to handle isn't safe to run multiple times concurrently.
How can I most simply set up a timer to run the task every 30 seconds while never overlapping executions? (I'm assuming System.Threading.Timer is the correct timer for this job, but could be mistaken).
You could do it with a Timer, but you would need to have some form of locking on your database scan and update. A simple lock to synchronize may be enough to prevent multiple runs from occurring.
That being said, it might be better to start a timer AFTER your operation is complete, and just use it one time, then stop it. Restart it after your next operation. This would give you 30 seconds (or N seconds) between events, with no chance of overlaps, and no locking.
Example :
System.Threading.Timer timer = null;
timer = new System.Threading.Timer((g) =>
{
Console.WriteLine(1); //do whatever
timer.Change(5000, Timeout.Infinite);
}, null, 0, Timeout.Infinite);
Work immediately .....Finish...wait 5 sec....Work immediately .....Finish...wait 5 sec....
I'd use Monitor.TryEnter in your elapsed code:
if (Monitor.TryEnter(lockobj))
{
try
{
// we got the lock, do your work
}
finally
{
Monitor.Exit(lockobj);
}
}
else
{
// another elapsed has the lock
}
I prefer System.Threading.Timer for things like this, because I don't have to go through the event handling mechanism:
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, 30000);
object updateLock = new object();
void UpdateCallback(object state)
{
if (Monitor.TryEnter(updateLock))
{
try
{
// do stuff here
}
finally
{
Monitor.Exit(updateLock);
}
}
else
{
// previous timer tick took too long.
// so do nothing this time through.
}
}
You can eliminate the need for the lock by making the timer a one-shot and re-starting it after every update:
// Initialize timer as a one-shot
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, Timeout.Infinite);
void UpdateCallback(object state)
{
// do stuff here
// re-enable the timer
UpdateTimer.Change(30000, Timeout.Infinite);
}
instead of locking (which could cause all of your timed scans to wait and eventually stack up). You could start the scan/update in a thread and then just do a check to see if the thread is still alive.
Thread updateDBThread = new Thread(MyUpdateMethod);
...
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(!updateDBThread.IsAlive)
updateDBThread.Start();
}
Starting from .NET 6 there is a new timer available, the PeriodicTimer. This is a lightweight async-enabled timer, that becomes the perfect tool when overlapping executions should be strictly forbidden. You use this timer by writing an asynchronous method with a loop, and invoking it to start the loop:
private Task _operation;
private CancellationTokenSource _operationCancellation = new();
//...
_operation = StartTimer();
//...
private async Task StartTimer()
{
PeriodicTimer timer = new(TimeSpan.FromSeconds(30));
while (true)
{
await timer.WaitForNextTickAsync(_operationCancellation.Token);
try
{
DoSomething();
}
catch (Exception ex)
{
_logger.LogError(ex);
}
}
}
Instead of using a CancellationTokenSource, you can also stop the loop by disposing the PeriodicTimer. In this case the await timer.WaitForNextTickAsync() will return false.
It is possible that the DoSomething will be invoked subsequently with smaller interval than 30 seconds, but it's impossible that it will be invoked in overlapping fashion, unless you start accidentally two asynchronous loops.
This timer does not support disabling and reenabling it. If you need this functionality you could look at the third-party Nito.AsyncEx.PauseTokenSource component.
In case you are targeting a .NET version earlier than .NET 6, you could look at this question for an alternative: Run async method regularly with specified interval.
You could use the AutoResetEvent as follows:
// Somewhere else in the code
using System;
using System.Threading;
// In the class or whever appropriate
static AutoResetEvent autoEvent = new AutoResetEvent(false);
void MyWorkerThread()
{
while(1)
{
// Wait for work method to signal.
if(autoEvent.WaitOne(30000, false))
{
// Signalled time to quit
return;
}
else
{
// grab a lock
// do the work
// Whatever...
}
}
}
A slightly "smarter" solution is as follow in pseudo-code:
using System;
using System.Diagnostics;
using System.Threading;
// In the class or whever appropriate
static AutoResetEvent autoEvent = new AutoResetEvent(false);
void MyWorkerThread()
{
Stopwatch stopWatch = new Stopwatch();
TimeSpan Second30 = new TimeSpan(0,0,30);
TimeSpan SecondsZero = new TimeSpan(0);
TimeSpan waitTime = Second30 - SecondsZero;
TimeSpan interval;
while(1)
{
// Wait for work method to signal.
if(autoEvent.WaitOne(waitTime, false))
{
// Signalled time to quit
return;
}
else
{
stopWatch.Start();
// grab a lock
// do the work
// Whatever...
stopwatch.stop();
interval = stopwatch.Elapsed;
if (interval < Seconds30)
{
waitTime = Seconds30 - interval;
}
else
{
waitTime = SecondsZero;
}
}
}
}
Either of these has the advantage that you can shutdown the thread, just by signaling the event.
Edit
I should add, that this code makes the assumption that you only have one of these MyWorkerThreads() running, otherwise they would run concurrently.
I've used a mutex when I've wanted single execution:
private void OnMsgTimer(object sender, ElapsedEventArgs args)
{
// mutex creates a single instance in this application
bool wasMutexCreatedNew = false;
using(Mutex onlyOne = new Mutex(true, GetMutexName(), out wasMutexCreatedNew))
{
if (wasMutexCreatedNew)
{
try
{
//<your code here>
}
finally
{
onlyOne.ReleaseMutex();
}
}
}
}
Sorry I'm so late...You will need to provide the mutex name as part of the GetMutexName() method call.

Categories

Resources