Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Full instructions: https://pasteboard.co/J2OX03H.png
Running Thread.Sleep on each thread seems to be preventing the Timer's ElapsedEventHandler from recalling Timer_Elapsed (FixedThreads) every x time causing it to print the threads way too fast. My goal is to have ScheduleThreads launch FixedThreads (prints threads info) every 15 seconds even if some of the threads don't finish executing/sleeping on time.
using FT = FixedThreads.FixedThreads;
using Timer = System.Timers.Timer;
namespace ScheduledThreads
{
class ScheduledThreads
{
static void Main(string[] args)
{
var timer = new Timer(15000);
timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
timer.Enabled = true;
while (timer.Enabled)
{
var info = Console.ReadKey(true);
if (info.KeyChar == 'e')
{
timer.Enabled = false;
}
}
}
static void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
FT.Main(null);
}
}
}
I call FixedThreads in ScheduledThreads
public class FixedThreads
{
public static void Main(string[] args)
{
Random random = new Random();
ThreadPool.SetMinThreads(100, 100);
for (int task = 0; task < 1000; task++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Execute), task);
Thread.Sleep(random.Next(5, 801)); //this prevents schedule to work if there's more than 10-15 threads/tasks
}
}
static void Execute(object callback)
{
Console.WriteLine($"Thread Id: {Thread.CurrentThread.ManagedThreadId}");
Thread.CurrentThread.Name = callback.ToString();
Console.WriteLine($"Thread Name: {Thread.CurrentThread.Name}");
Console.WriteLine($"Daemon/Background Thread: {Thread.CurrentThread.IsBackground}");
}
}
Are you seeing any output at all from the console? If not you might be deadlocked waiting for the Console.ReadKey to finish before the threads can write to the console output stream. This is because Console.WriteLine and Console.ReadKey both obtain a lock to the same object.
The Console.WriteLine only obtains the lock the first time it outputs to the stream, so an easy way to test that is to add a Console.WriteLine before you do a ReadKey.
You're probably running into the maximum thread count of the default thread pool. It's the default thread pool that handles the Timer.
https://learn.microsoft.com/en-us/dotnet/standard/threading/the-managed-thread-pool
Thread.Sleep will block the thread and is usually a lazy way to get what you're really after. There are better scheduling methods that won't block or be as heavy-weight as a Thread.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am making a food ordering desktop application , so i want to calculate time between ordering food and delivering food so i added timers to the app and made a start and end buttons , on starting i start a time and put it interval value ,make a variable counter, count and save its value on end button to database , what i want to made is to start a new timer dynamically on new orders and when ending an order stop its timer
i tried inserting 3 timers and made variables c1,c2,c3 and made a loop to start timers on every order if interval!=null , but i didn't know how to stop a specific timer on ending the order
code :
int c1=0;
int c2=0;
int c3=0;
private void button_start_Click(object sender, EventArgs e)
{
if (timer1.Interval == null)
{
timer1.Start();
timer1.Interval = 1000;
}
else if (timer2.Interval == null)
{
timer2.Start();
timer2.Interval = 1000;
}
else if (timer3.Interval == null)
{
timer3.Start();
timer3.Interval = 1000;
}
}
Well as you have not shown us any code, let me assume that you at least have a class to encapsulate order.
public class Order
{
public int OrderNumber{get;set;}
///other properties
}
Now if you add following two properties and a method, your problem is resolved.
public class Order
{
public int OrderNumber{get;set;}
//other properties
public DateTime OrderPlacedOn{get;set;}
public DateTime OrderCompletedOn{get;set;}
public TimeSpan TimeToComplete()
{
if(OrderCompletedOn==DateTime.MinValue)//order not completed yet
return TimeSpan.FromSeconds(0);
return OrderCompletedOn - OrderPlacedOn;
}
}
This saves you from keeping countless timers. You can set values of start and complete on clicking of your buttons.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I've been working on a timer in c# just to mess around since I've never done it before. I wanted to have the OnTimedEvents method I was declaring in a separate class as I will be calling it in various other classes for various other tests, but I cannot invoke it properly without getting errors. Specifically, I am getting No Overload Method for Method '' Takes 0 Arguments. I cannot work around this as I have with other methods. This is the code:
class MSOfficeApps {
public static Timer aTimer;
public void appWord() {
var programCS = new Program();
Microsoft.Office.Interop.Word.Application WordObj;
WordObj = (Microsoft.Office.Interop.Word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
for(int i = 0; i < WordObj.Windows.Count; i++) {
object idx = i + 1;
Microsoft.Office.Interop.Word.Window WinObj = WordObj.Windows.get_Item(ref idx);
Console.WriteLine(WinObj.Document.FullName);
aTimer = new System.Timers.Timer(600000); //Sets timer to 6 minute increments
aTimer.Elapsed += ElapsedEventHandler(programCS.OnTimedEvent()); //Throwing an error at programCS.OnTimedEvent()
}
}
And this is what I'm trying to call
class Program {
private static void Main(string[] args) {
SearchProcesses sP = new SearchProcesses();
sP.BuildProcessLists();
Console.WriteLine("Press Enter to exit the program...");
Console.ReadLine();
}
public static void OnTimedEvent(Object source, ElapsedEventArgs e) {
Console.WriteLine("Event was raised at {0}", e.SignalTime);
}
}
Please advise :)
Change
aTimer.Elapsed += ElapsedEventHandler(programCS.OnTimedEvent());
to
aTimer.Elapsed += ElapsedEventHandler(programCS.OnTimedEvent);
You are invoking programCS.OnTimedEvent, rather than passing it as a reference (and invoking it without arguments), thus the error.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
what is another command for 'Goto' ? I am using VSTO to make a ribbon for excel and is doesnt seem to support Goto, and I am trying to create a loop.
Edit: This is the loop i am trying to create :
TimeSpan startTimeSpan = new TimeSpan(0, 0, 0, 20);
TimeSpan timeDecrease = TimeSpan.FromSeconds(1);
private Timer timer = new Timer();
public void Ribbon_Load(Office.IRibbonUI ribbonUI)
{
timer.Interval = 1000;
this.ribbon = ribbonUI;
timer.Tick += timer_Tick;
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
if (startTimeSpan.ToString() != "00:00:00")
{
startTimeSpan = startTimeSpan - timeDecrease;
ribbon.InvalidateControl("timerLabel");
}
else
{
//when timer drop to "00:00:00" then loop to "TimeSpan startTimeSpan = new TimeSpan(0, 0, 0, 20);"
}
}
You probably want to be using a while loop, with the exit condition in the while statement, and use break to quit the loop before the exit condition is reached, or continue to skip the current iteration of the loop and go on to the next.
C# does support goto command, but it isn't for looping. Jump statements are very often not the best solution.
goto - http://msdn.microsoft.com/en-us/library/13940fs2.aspx
If you are trying to loop just use a looping statement.
looping - http://msdn.microsoft.com/en-us/library/ms228598(v=vs.90).aspx
You can find a lot of q&a on excel VSTO.
Whats wrong with something like:
for (int i = selectedRange.Rows.Count; i > 0; i--)
{
---YOUR CODE HERE---
}
OR
foreach (Excel.Range row in rng.Areas[1].Rows)
{
---YOUR CODE HERE---
}
Is there any clever method out there to make my executeEveryDayMethod() execute once a day, without having to involve the Windows TaskScheduler?
I achieved this by doing the following...
Set up a timer that fires every 20 minutes (although the actual timing is up to you - I needed to run on several occasions throughout the day).
on each Tick event, check the system time. Compare the time to the scheduled run time for your method.
If the current time is less than the scheduled time, check a in some persistent storage to get the datetime value of the last time the method ran.
If the method last ran more than 24 hours ago, run the method, and stash the datetime of this run back to your data store
If the method last ran within the last 24 hours, ignore it.
HTH
*edit - code sample in C# :: Note : untested...
using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Timer t1 = new Timer();
t1.Interval = (1000 * 60 * 20); // 20 minutes...
t1.Elapsed += new ElapsedEventHandler(t1_Elapsed);
t1.AutoReset = true;
t1.Start();
Console.ReadLine();
}
static void t1_Elapsed(object sender, ElapsedEventArgs e)
{
DateTime scheduledRun = DateTime.Today.AddHours(3); // runs today at 3am.
System.IO.FileInfo lastTime = new System.IO.FileInfo(#"C:\lastRunTime.txt");
DateTime lastRan = lastTime.LastWriteTime;
if (DateTime.Now > scheduledRun)
{
TimeSpan sinceLastRun = DateTime.Now - lastRan;
if (sinceLastRun.Hours > 23)
{
doStuff();
// Don't forget to update the file modification date here!!!
}
}
}
static void doStuff()
{
Console.WriteLine("Running the method!");
}
}
}
Take a look at quartz.net. It is a scheduling library for .net.
More specifically take a look here.
If the time when it is run is not relevant and can be reset each time the program starts you can just set a timer, which is the easiest thing to do. If that's not acceptable it starts getting more complex, like the solution presented here and which still doesn't solve the persistence problem, you need to tackle that separately if you truly wish to do what Scheduled Tasks would. I'd really consider again if it's worth going through all the trouble to replicate a perfectly good existing functionality.
Here's a related question (Example taken from there).
using System;
using System.Timers;
public class Timer1
{
private static Timer aTimer = new System.Timers.Timer(24*60*60*1000);
public static void Main()
{
aTimer.Elapsed += new ElapsedEventHandler(ExecuteEveryDayMethod);
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void ExecuteEveryDayMethod(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}
public partial class Main : Form
{
public Main( ) // Windows Form is called Main
{
InitializeComponent( );
}
private void Main_Load( object sender, EventArgs e )
{
/*
This example uses a System.Windows.Forms Timer
This code allows you to schedule an event at any given time in one day.
In this example the timer will tick at 3AM.
*/
Int32 alarm = GetAlarmInMilliseconds( 3, 0, 0 ); // Milliseconds until 3:00 am.
timer_MessageCount.Interval = alarm; // Timer will tick at 3:00am.
timer_MessageCount.Start( );
}
private Int32 GetAlarmInMilliseconds(Int32 eventHour, Int32 eventMinute, Int32 eventSecond )
{
DateTime now = DateTime.Now;
DateTime eventTime = new DateTime( now.Year, now.Month, now.Day, eventHour, eventMinute, eventSecond );
TimeSpan ts;
if ( eventTime > now )
{
ts = eventTime - now;
}
else
{
eventTime = eventTime.AddDays( 1 );
ts = eventTime - now;
}
Console.WriteLine("Next alarm in: {0}", ts );
return ( Int32 ) ts.TotalMilliseconds;
}
static void DoSomething( )
{
Console.WriteLine( "Run your code here." );
}
private void timer_MessageCount_Tick( object sender, EventArgs e )
{
DoSomething( );
Int32 alarm = GetAlarmInMilliseconds( 3, 0, 0 ); // Next alarm time = 3AM
timer_MessageCount.Interval = alarm;
}
}
Suppose you have the daily time in _Settings.DataCleanupTime in Format "hh:mm:ss"
//note the namespace, there are 4 different timers in .NET
System.Threading.Timer _Timer;
DateTime now = DateTime.Now;
//convert "hh:mm:ss" to three integers
var dateparts = _Settings.DataCleanupTime.Split(new char[] { ':' }).Select(p => Convert.ToInt32(p)).ToArray();
DateTime firstTime = new DateTime(now.Year, now.Month, now.Day, dateparts[0], dateparts[1], dateparts[2]);
//e.g. firsttime is today at 2am and it is already 6am
if(firstTime < now)
{
//first run will be tomorrow
firstTime = firstTime.AddDays(1);
}
int delay = Convert.ToInt32((firstTime - now).TotalMilliseconds);
_Timer = new Timer(DoWork, state:null, delay, 3600 * 24 * 1000);
The signature of DoWork is:
public void DoWork(Object state)
To stop the timer just call:
_Timer.Dispose();
You could query time and run if your within some time frame, that way even if the machine goes off you'll call the method or use a timer like Vinko's suggestion.
But the better solution (akin to older CRON versions, so its a proven pattern) is to have some persistent data, with the cheapest solution I can think of right now being a blank file, check its last modified attribute, and if it hasn't been modified within the last 24 hours you touch it and run your method. This way you assure the method gets run first thing in the case the application is out for the weekend for example.
I've done this in C# before, but its was a year ago at another Job, so I don't have the code but it was about 20 lines (with comments and all) or so.
To run the job once daily between 7 and 8pm, i set up a timer with interval = 3600000 ms and then just execute the following code for timer tick.
private void timer1_Tick(object sender, EventArgs e)
{
//ensure that it is running between 7-8pm daily.
if (DateTime.Now.Hour == 19)
{
RunJob();
}
}
An hour window is fine for me. Extra granularity on time will require a smaller interval on the timer (60000 for a minute) and including minutes on the if.
eg
{
//ensure that it is running at 7:30pm daily.
if (DateTime.Now.Hour == 19 && DateTime.Now.Minute == 30)
{
RunJob();
}
}
If you only want to run it once a day and don't care when, this will work (will run just after midnight).
Declare a DateTime variable:
DateTime _DateLastRun;
In your startup, set the initial date value:
_DateLastRun = DateTime.Now.Date;
In the logic area where you want to check whether to perform the action:
if (_DateLastRun < DateTime.Now.Date)
{
// Perform your action
_DateLastRun= DateTime.Now.Date;
}
You can try this solution.
public Main()
{
StartService();
}
public async Task StartService(CancellationToken token = default(CancellationToken))
{
while (!token.IsCancellationRequested)
{
ExecuteFunction();
try
{
await Task.Delay(TimeSpan.FromDays(1), token);
}
catch (TaskCanceledException)
{
break;
}
}
}
public async Task ExecuteFunction()
{
...
}
Here is how you can do it if you're running a Windows Forms Application. But you need to configure a setting so that you can store the last date the event was fired. If you never intend to close the app you can just store the date as a static value.
Im using a timer to fire the event, as following:
private void tmrAutoBAK_Tick(object sender, EventArgs e)
{
if (BakDB.Properties.Settings.Default.lastFireDate != DateTime.Now.ToString("yyyy-MM-dd"))
{
tmrAutoBAK.Stop(); //STOPS THE TIMER IN CASE OF EVENTUAL MESSAGEBOXES.
createBakup(); //EVENT
BakDB.Properties.Settings.Default.lastFireDate = DateTime.Now.ToString("yyyy-MM-dd"); //STORING CURRENT DATE TO SETTINGS FILE.
BakDB.Properties.Settings.Default.Save(); //SAVING THE SETTING FILE.
tmrAutoBAK.Start(); //RESTARTING TIMER
}
}
This is my very simple solution to execute a method once once a day:
private static DateTime _LastAccessedTime;
private static void OnceADayCode() // method that you want access once a day
{
_LastAccessedTime = DateTime.Today;
}
public static void PublicMethod() // this can be a method called from outside
{
if (_LastAccessedTime != DateTime.Today)
{
OnceADayCode();
}
}
with the same logic you can also use:
private static DateTime _LastAccessedTime;
private static void OnceADayCode()
{
if (_LastAccessedTime.Today != DateTime.Today)
{
// code that you want access once a day
_LastAccessedTime = DateTime.Today;
}
}