I have a console application that runs at :00 of every hour. This console application copies files at :15 and :30 of the very same hour.
This was my initial code, where I use a WHILE loop to check the current minute. I would like to replace the WHILE loop with a System.Threading.Timer.
Using Threading.Timer and without using a loop, how can I launch Thread0 at 15 minutes after the start of the console app and Thread1 at 30 minutes? I do not want to use 3rd-party, open-source solutions.
CancellationTokenSource cts0 = new CancellationTokenSource();
CancellationTokenSource cts1 = new CancellationTokenSource();
Thread Thread0, Thread1;
DateTime TaskRunDateTime = DateTime.Now;
DateTime RightNow = DateTime.Now;
while (!thread0Running || !thread1Running)
{
if (RightNow.Minute == 15)
{
thread0Running = true;
Class myClass0 = new Class();
Thread0 = new Thread(() => myClass0.CopyFiles(15, cts0.Token));
Thread0.Start();
}
else if (RightNow.Minute == 30)
{
thread1Running = true;
Class myClass1 = new Class();
Thread1 = new Thread(() => myClass1.CopyFiles(30, cts1.Token));
Thread1.Start();
}
RightNow = DateTime.Now;
}
for (; ; )
{
fileCount = Directory.GetFiles(destPath, FileDate + "*.xml").Length;
If (fileCount == 20)
{
// All 20 files have been copied because the two threads have finished
RunExternalReportGeneratorEXE();
break;
}
else if (RightNow >= TaskRunDateTime.AddHours(2))
{
// Task took over 2 hours to complete.
// Cancel Thread0, Thread1 and run 3rd-party executable.
cts0.Cancel();
cts1.Cancel();
RunExternalReportGeneratorEXE();
break;
}
At the point you application starts you can calculate how long until X:15 and X:30 will fall. You could then use the Timer's constructor to schedule the start time of the timer callback and the frequency.
Create two ManualResetEvent objects that you can wait on. Then create two timers:
ManualResetEvent Copy1Done = new ManualResetEvent(false);
ManualResetEvent Copy2Done = new ManualResetEvent(false);
Timer t1 = new Timer((s) =>
{
Class myClass0 = new Class();
myClass0.CopyFiles(15, cts0.Token);
Copy1Done.Set();
}, null, TimeSpan.FromMinutes(15), TimeSpan.FromMilliseconds(-1));
Timer t1 = new Timer((s) =>
{
Class myClass1 = new Class();
myClass0.CopyFiles(30, cts1.Token);
Copy2Done.Set();
}, null, TimeSpan.FromMinutes(30), TimeSpan.FromMilliseconds(-1));
Those are one-shot timers; they'll fire once, and then won't fire again.
Now, you want to wait up to two hours for the copies to complete. That's where the ManualResetEvent objects come in. Create an array of the events:
WaitHandle[] handles = new WaitHandle[] {Copy1Done, Copy2Done};
// wait for both events to be signaled, or for two hours
if (!WaitHandle.WaitAll(handles, TimeSpan.FromHours(2)))
{
// took too long. Cancel the copies.
cts0.Cancel();
cts1.Cancel();
// you might want to wait here for the threads to exit.
// otherwise you might have a problem with a locked file.
}
// and run the program
RunExternalReportGeneratorEXE();
I don't want to write the whole code here for you but to give you an idea what you can do with thread timer:
void CreateTimer()
{
// Create an event to signal the timeout count threshold in the
// timer callback.
AutoResetEvent autoEvent = new AutoResetEvent(false);
// Create an inferred delegate that invokes methods for the timer.
TimerCallback tcb = CheckStatus;
// Create a timer that signals the delegate to invoke
// CheckStatus after 15 minutes.
// thereafter.
Console.WriteLine("{0} Creating timer.\n", DateTime.Now.ToString("h:mm:ss.fff"));
System.Threading.Timer Timer stateTimer = new Timer(tcb, autoEvent, 1000 * 60 *15, 0);
//Wait for 15 minutes
autoEvent.WaitOne(1000 * 60 *15, false);
stateTimer = new Timer(tcb, null, 1000 * 60 *30, 0);
}
// This method is called by the timer delegate.
public void CheckStatus(Object stateInfo)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), stateInfo);
}
public void DoWork(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
autoEvent.Set();
//Change your worktype here.
CancellationTokenSource cts0 = new CancellationTokenSource();
Class myClass1 = new Class();
myClass1.CopyFiles(30, cts0.Token);
}
Related
I am making an application in Xamarin Forms in which I need to call a method every x time for x time (e.g. every 5 seconds for 2 minutes). How can it be done?
I have only found information on how to call a method every x time, but this is not enough for what I am looking for.
This is what I have tried. This calls MyMethod after 15 seconds have elapsed:
await Task.Delay(new TimeSpan(0, 0, 15)).ContinueWith(async o =>
{
MyMethod();
});
And this calls MyMethod every 5 seconds:
var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromSeconds(5);
var timer = new System.Threading.Timer((e) =>
{
MyMethod();
}, null, startTimeSpan, periodTimeSpan);
What I need is to call MyMethod every x seconds for x amount of time.
Don't forget that Xamarin is based on C# language, so you can use C# language.
According to Microsoft documentation Timer class , you can do something like this:
public class Example
{
private static System.Timers.Timer aTimer;
public static void Main()
{
SetTimer();
}
private static void SetTimer()
{
// Create a timer with a five second interval.
aTimer = new System.Timers.Timer(5000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
// Do your instruction while two minutes here
// You could create another Timer which repeat instruction during two minutes
}
}
You could set a limit seconds for the Timer.
For example you want do something every 5 seconds for 2 minutes.
int sec = 120000; // 2 minutes
int period = 5000; //every 5 seconds
TimerCallback timerDelegate = new TimerCallback(Tick);
Timer _dispatcherTimer = new System.Threading.Timer(timerDelegate, null, period, period);// if you want the method to execute immediately,you could set the third parameter to null
private void Tick(object state)
{
Device.BeginInvokeOnMainThread(() =>
{
sec -= period;
if (sec >= 0)
{
//do something
}
else
{
_dispatcherTimer.Dispose();
}
});
}
You could do something like this:
You'll probably need a Thread that is running in the background:
private async void CallMethodEveryXSecondsYTimes(int waitSeconds, int durationSeconds)
{
await Task.Run(() => {
var end = DateTime.Now.AddSeconds(durationSeconds);
while (end > DateTime.Now)
{
Dispatcher.BeginInvokeOnMainThread(() =>
{
YourMethod();
});
Thread.Sleep(waitSeconds*1000);
}
});
}
I am trying to refresh my frame every 17ms with a timer.
Timer timer = new Timer(17);
timer.Elapsed += ResetFrame;
timer.Start();
But instead of waiting for 17ms and then repeating, it waited for the frame refresh to complete and then wait for 17msfor the next repeat. This causes the frame to be refreshed every 28ms. How to synchronize it with real time?
To have a real time timer having a very short interval, you can take a look at this article:
Real Time Timer in C#
In Dot Net, following timers are not real time.
System.Windows.Forms.Timer
System.Timers.Timer
System.Threading.Timer
Means if you want to run your code at every 100 millisecond then above
timer fire even around 110 millisecond or later. Windows is not a real
time OS because of this .Net is also not a real time.
To create a real time timer in C# you have to write custom code that
can hold CPU to run your code at right time.
class Program
{
static void Main(string[] args)
{
Console.ReadLine();
Console.WriteLine("Running");
RealTimeTimerTest obj = new RealTimeTimerTest();
obj.Run();
}
}
public class RealTimeTimerTest
{
List<DateTime> lst = new List<DateTime>();
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
public void Run()
{
int Tick = 100;
int Sleep = Tick - 20;
long OldElapsedMilliseconds = 0;
sw.Start();
while (sw.IsRunning)
{
long ElapsedMilliseconds = sw.ElapsedMilliseconds;
long mod = (ElapsedMilliseconds % Tick);
if (OldElapsedMilliseconds != ElapsedMilliseconds && (mod == 0 || ElapsedMilliseconds > Tick))
{
//-----------------Do here whatever you want to do--------------Start
lst.Add(DateTime.Now);
//-----------------Do here whatever you want to do--------------End
//-----------------Restart----------------Start
OldElapsedMilliseconds = ElapsedMilliseconds;
OldElapsedMilliseconds = 0;
sw.Reset();
sw.Start();
System.Threading.Thread.Sleep(Sleep);
//-----------------Restart----------------End
}
//------------Must define some condition to break the loop here-----------Start
if (lst.Count > 500)
{
Write();
break;
}
//-------------Must define some condition to break the loop here-----------End
}
}
private void Write()
{
System.IO.StreamWriter sw = new System.IO.StreamWriter("d:\\text.txt", true);
foreach (DateTime dtStart in lst)
sw.WriteLine(dtStart.ToString("HH:mm:ss.ffffff")); sw.Close();
}
}
Also that:
Most accurate timer in .NET?
High resolution timer
High resolution timer in C#
Microsecond and Millisecond C# Timer
Precision-Repeat-Action-On-Interval-Async-Method
I'm working on windows service and I want to call a method from OnStart every minute. I originally had a forever while loop but then the service wouldn't install.
while (true)
{
Stopwatch stopWatch = new Stopwatch();
int totalTime = 0;
stopWatch.Start();
MethodToCall();
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
totalTime = ts.Seconds * 1000 + ts.Milliseconds;
if (totalTime < 60000)
{
Thread.Sleep(60000 - totalTime);
//ManualResetEvent.WaitOne(10000);
}
else
{
Thread.Sleep(30000);
}
}
So, how can I make my method call every minute BUT when the method exceeds one minute it will wait N number of minutes(let's say 30 seconds) and then start over by calling the method.
Something like this should work. With the AutoReset flag set to false, the timer will only fire once, after the specified interval time. In the finally block, we make sure to restart the timer countdown, waiting for the interval to elapse again.
var interval = TimeSpan.FromMinutes( 1 );
var timer = new System.Timers.Timer( interval.TotalMilliseconds ) { AutoReset = false };
timer.Elapsed += ( sender, eventArgs ) =>
{
var start = DateTime.Now;
try
{
// do work
}
finally
{
var elapsed = DateTime.Now - start;
if ( elapsed < interval )
timer.Interval = (interval - elapsed).TotalMilliseconds;
else
timer.Interval = TimeSpan.FromSeconds( 30 ).TotalMilliseconds;
timer.Start();
}
};
timer.Start();
Source for Timer.Elapsed (note the bit about setting Interval resetting the countdown)
There are two solutions depending on what you want. Do you want to do work once a minute on the minute and always wait for the next minute? Or do you want to run no more than once a minute but it's okay to "catch up" if you fall behind?
In other words, if processing takes 80 seconds then does the next work start immediately or wait until T=120?
The first is easier, but note that I haven't tested this and it's just a guideline:
AutoResetEvent waitHandle = new AutoResetEvent(false);
System.Timer(() => waitHandle.Set(), null, TimeSpan.FromMinutes(1), TimeSpan.FromMilliseconds(-1));
while (true)
{
// Do stuff
waitHandle.WaitOne();
}
The second is just a bit harder.
ManualResetEvent waitHandle = new ManualResetEvent (false);
System.Timer(() => waitHandle.Set(), null, TimeSpan.FromMinutes(1), TimeSpan.FromMilliseconds(-1));
while (true)
{
// Do stuff
waitHandle.Reset();
waitHandle.WaitOne();
}
I have a windows service (written in C#) that use the task parallel library dll to perform some parallel tasks (5 tasks a time)
After the tasks are executed once I would like to repeat the same tasks on an on going basis (hourly). Call the QueuePeek method
Do I use a timer or a counter like I have setup in the code snippet below?
I am using a counter to set up the tasks, once I reach five I exit the loop, but I also use a .ContinueWith to decrement the counter, so my thought is that the counter value would be below 5 hence the loop would continue. But my ContinueWith seems to be executing on the main thread and the loop then exits.
The call to DecrementCounter using the ContinueWith does not seem to work
FYI : The Importer class is to load some libraries using MEF and do the work
This is my code sample:
private void QueuePeek()
{
var list = SetUpJobs();
while (taskCounter < 5)
{
int j = taskCounter;
Task task = null;
task = new Task(() =>
{
DoLoad(j);
});
taskCounter += 1;
tasks[j] = task;
task.ContinueWith((t) => DecrementTaskCounter());
task.Start();
ds.SetJobStatus(1);
}
if (taskCounter == 0)
Console.WriteLine("Completed all tasks.");
}
private void DoLoad(int i)
{
ILoader loader;
DataService.DataService ds = new DataService.DataService();
Dictionary<int, dynamic> results = ds.AssignRequest(i);
var data = results.Where(x => x.Key == 2).First();
int loaderId = (int)data.Value;
Importer imp = new Importer();
loader = imp.Run(GetLoaderType(loaderId));
LoaderProcessor lp = new LoaderProcessor(loader);
lp.ExecuteLoader();
}
private void DecrementTaskCounter()
{
Console.WriteLine(string.Format("Decrementing task counter with threadId: {0}",Thread.CurrentThread.ManagedThreadId) );
taskCounter--;
}
I see a few issues with your code that can potentially lead to some hard to track-down bugs. First, if using a counter that all of the tasks can potentially be reading and writing to at the same time, try using Interlocked. For example:
Interlocked.Increment(ref _taskCounter); // or Interlocked.Decrement(ref _taskCounter);
If I understand what you're trying to accomplish, I think what you want to do is to use a timer that you re-schedule after each group of tasks is finished.
public class Worker
{
private System.Threading.Timer _timer;
private int _timeUntilNextCall = 3600000;
public void Start()
{
_timer = new Timer(new TimerCallback(QueuePeek), null, 0, Timeout.Infinite);
}
private void QueuePeek(object state)
{
int numberOfTasks = 5;
Task[] tasks = new Task[numberOfTasks];
for(int i = 0; i < numberOfTasks; i++)
{
tasks[i] = new Task(() =>
{
DoLoad();
});
tasks[i].Start();
}
// When all tasks are complete, set to run this method again in x milliseconds
Task.Factory.ContinueWhenAll(tasks, (t) => { _timer.Change(_timeUntilNextCall, Timeout.Infinite); });
}
private void DoLoad() { }
}
I'm running into a common pattern in the code that I'm writing, where I need to wait for all threads in a group to complete, with a timeout. The timeout is supposed to be the time required for all threads to complete, so simply doing Thread.Join(timeout) for each thread won't work, since the possible timeout is then timeout * numThreads.
Right now I do something like the following:
var threadFinishEvents = new List<EventWaitHandle>();
foreach (DataObject data in dataList)
{
// Create local variables for the thread delegate
var threadFinish = new EventWaitHandle(false, EventResetMode.ManualReset);
threadFinishEvents.Add(threadFinish);
var localData = (DataObject) data.Clone();
var thread = new Thread(
delegate()
{
DoThreadStuff(localData);
threadFinish.Set();
}
);
thread.Start();
}
Mutex.WaitAll(threadFinishEvents.ToArray(), timeout);
However, it seems like there should be a simpler idiom for this sort of thing.
I still think using Join is simpler. Record the expected completion time (as Now+timeout), then, in a loop, do
if(!thread.Join(End-now))
throw new NotFinishedInTime();
With .NET 4.0 I find System.Threading.Tasks a lot easier to work with. Here's spin-wait loop which works reliably for me. It blocks the main thread until all the tasks complete. There's also Task.WaitAll, but that hasn't always worked for me.
for (int i = 0; i < N; i++)
{
tasks[i] = Task.Factory.StartNew(() =>
{
DoThreadStuff(localData);
});
}
while (tasks.Any(t => !t.IsCompleted)) { } //spin wait
This doesn't answer the question (no timeout), but I've made a very simple extension method to wait all threads of a collection:
using System.Collections.Generic;
using System.Threading;
namespace Extensions
{
public static class ThreadExtension
{
public static void WaitAll(this IEnumerable<Thread> threads)
{
if(threads!=null)
{
foreach(Thread thread in threads)
{ thread.Join(); }
}
}
}
}
Then you simply call:
List<Thread> threads=new List<Thread>();
//Add your threads to this collection
threads.WaitAll();
Since the question got bumped I will go ahead and post my solution.
using (var finished = new CountdownEvent(1))
{
for (DataObject data in dataList)
{
finished.AddCount();
var localData = (DataObject)data.Clone();
var thread = new Thread(
delegate()
{
try
{
DoThreadStuff(localData);
threadFinish.Set();
}
finally
{
finished.Signal();
}
}
);
thread.Start();
}
finished.Signal();
finished.Wait(YOUR_TIMEOUT);
}
Off the top of my head, why don't you just Thread.Join(timeout) and remove the time it took to join from the total timeout?
// pseudo-c#:
TimeSpan timeout = timeoutPerThread * threads.Count();
foreach (Thread thread in threads)
{
DateTime start = DateTime.Now;
if (!thread.Join(timeout))
throw new TimeoutException();
timeout -= (DateTime.Now - start);
}
Edit: code is now less pseudo. don't understand why you would mod an answer -2 when the answer you modded +4 is exactly the same, only less detailed.
This may not be an option for you, but if you can use the Parallel Extension for .NET then you could use Tasks instead of raw threads and then use Task.WaitAll() to wait for them to complete.
I read the book C# 4.0: The Complete Reference of Herbert Schildt. The author use join to give a solution :
class MyThread
{
public int Count;
public Thread Thrd;
public MyThread(string name)
{
Count = 0;
Thrd = new Thread(this.Run);
Thrd.Name = name;
Thrd.Start();
}
// Entry point of thread.
void Run()
{
Console.WriteLine(Thrd.Name + " starting.");
do
{
Thread.Sleep(500);
Console.WriteLine("In " + Thrd.Name +
", Count is " + Count);
Count++;
} while (Count < 10);
Console.WriteLine(Thrd.Name + " terminating.");
}
}
// Use Join() to wait for threads to end.
class JoinThreads
{
static void Main()
{
Console.WriteLine("Main thread starting.");
// Construct three threads.
MyThread mt1 = new MyThread("Child #1");
MyThread mt2 = new MyThread("Child #2");
MyThread mt3 = new MyThread("Child #3");
mt1.Thrd.Join();
Console.WriteLine("Child #1 joined.");
mt2.Thrd.Join();
Console.WriteLine("Child #2 joined.");
mt3.Thrd.Join();
Console.WriteLine("Child #3 joined.");
Console.WriteLine("Main thread ending.");
Console.ReadKey();
}
}
I was tying to figure out how to do this but i could not get any answers from google.
I know this is an old thread but here was my solution:
Use the following class:
class ThreadWaiter
{
private int _numThreads = 0;
private int _spinTime;
public ThreadWaiter(int SpinTime)
{
this._spinTime = SpinTime;
}
public void AddThreads(int numThreads)
{
_numThreads += numThreads;
}
public void RemoveThread()
{
if (_numThreads > 0)
{
_numThreads--;
}
}
public void Wait()
{
while (_numThreads != 0)
{
System.Threading.Thread.Sleep(_spinTime);
}
}
}
Call Addthreads(int numThreads) before executing a thread(s).
Call RemoveThread() after each one has completed.
Use Wait() at the point that you want to wait for all the threads to complete
before continuing
Possible solution:
var tasks = dataList
.Select(data => Task.Factory.StartNew(arg => DoThreadStuff(data), TaskContinuationOptions.LongRunning | TaskContinuationOptions.PreferFairness))
.ToArray();
var timeout = TimeSpan.FromMinutes(1);
Task.WaitAll(tasks, timeout);
Assuming dataList is the list of items and each item needs to be processed in a separate thread.
Here is an implementation inspired by Martin v. Löwis's answer:
/// <summary>
/// Blocks the calling thread until all threads terminate, or the specified
/// time elapses. Returns true if all threads terminated in time, or false if
/// at least one thread has not terminated after the specified amount of time
/// elapsed.
/// </summary>
public static bool JoinAll(IEnumerable<Thread> threads, TimeSpan timeout)
{
ArgumentNullException.ThrowIfNull(threads);
if (timeout < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(timeout));
Stopwatch stopwatch = Stopwatch.StartNew();
foreach (Thread thread in threads)
{
if (!thread.IsAlive) continue;
TimeSpan remaining = timeout - stopwatch.Elapsed;
if (remaining < TimeSpan.Zero) return false;
if (!thread.Join(remaining)) return false;
}
return true;
}
For measuring the remaining time, instead of the DateTime.Now it uses a Stopwatch. The Stopwatch component is not sensitive to system-wide clock adjustments.
Usage example:
bool allTerminated = JoinAll(new[] { thread1, thread2 }, TimeSpan.FromSeconds(10));
The timeout must be a positive or zero TimeSpan. The Timeout.InfiniteTimeSpan constant is not supported.