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.
}
Related
I have an application that calls static methods in a DLL every 60 seconds as part of a system "self-check" application. When I manually run the methods, they all complete in less than 10 seconds. My problem is the timer.elapsed event is firing twice, one right after the other. To add to that, for each time the timer elapses, the event fires one more time. (e.g. first time it's 2 firings, second it's 3, third it's 4, etc.) I have tried setting the timer.AutoReset = false along with setting timer.Enabled = false at the beginning of the elapsed event and then setting it to true at the end of the event. I've tried resetting the interval in the event. Every post I have found indicates that the above actions should have resolved this problem. Can anyone help me find what I'm missing?
static Timer cycle = new Timer();
static int cycCount = 0;
static void Main(string[] args)
{
Console.WriteLine("Firebird Survivor Auto Cycle Started.");
Console.CancelKeyPress += Console_CancelKeyPress;
cycle.Interval = 60000; //set interval for service checks.
cycle.Elapsed += new ElapsedEventHandler(CycleComplete_Elapsed);
cycle.AutoReset = false;
cycle.Enabled = true;
cycle.Elapsed += CycleComplete_Elapsed;
while (1 == 1) //stop main method from completing indefinitely
{
//WAIT FOR TIMER TO ELAPSE
}
}
private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
cycle = null;
}
static void CycleComplete_Elapsed(object sender, ElapsedEventArgs e) //method triggered by timer
{
cycle.Enabled = false;
cycCount++;
WormholeServiceControls.CheckWormHoleStatus();
TimeControls.CheckTimePl(); //call time check
PegasusServiceControls.CheckPegasusStatus(null);
Console.Clear();
Console.WriteLine("--------------------------");
Console.WriteLine(String.Format("| Successful Cycles: {0} |", cycCount));
Console.WriteLine("--------------------------");
cycle.Enabled = true;
}
It seems your problem comes from the event handling you are doing. You are assigning the Elapsed event more than one time:
cycle.Elapsed += new ElapsedEventHandler(CycleComplete_Elapsed);
cycle.Elapsed += CycleComplete_Elapsed;
Why this two lines?. You will be all right with only this:
cycle.Elapsed += new ElapsedEventHandler(CycleComplete_Elapsed);
I'm developing an Web API (which works quite well). What's missing?
Here is sample code of Get Action:
public IEnumerable<xxxx> Get()
{
IEnumerable<xxxx> yyyy = new List<xxxx>();
//get yyyy from database
timer = new Timer();
timer.AutoReset = true;
timer.Enabled = true;
timer.Interval = 5000; //miliseconds
timer.Elapsed += timer_Elapsed;
timer.Start();
return yyyy;
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
//code to be executed when timer elapses...
}
So once a request is received, timer will be initialized and will fire Elapsed event at interval of 5 seconds. On next subsequent request this continues....
The expected behavior is such that:
Initialize Request -1
Initialize Timer -1
If another request from same client is received within 5 seconds, timer must not fire elapsed event.
If no request is received from same client within 5 seconds, timer should elapse and fire the event.
Also the timer has nothing to do with client(s).
Here is further business scenario related to this....
I'm developing a Web API that will be consumed by an electronic device when switched on. The device will keep sending it's ON status as long as the power is available. As soon as, user turns off the switch, the request to the server stops.
These status are updated into database whether device is ON or OFF. Now the trickier part was to identify when device turns off (complicated because the server does not know anything if the device stops sending any request). So for each devices there is a separate timer.
First of all, thank you #Patrick Hofman to guide me and think out of box...
I implemented a class having static property inside it.
public class DeviceContainer
{
public static List<DevTimer> timers=new List<DevTimer>();
}
public class DevTimer:Timer
{
public string Identifier {get; set;}
public bool IsInUse{get; set;}
}
and then in above code (in question), I made following changes:
public IEnumerable<xxxx> Get(string Id)
{
//Check if timer exists in
if(!DeviceContainer.timers.Any(s=>s.Identifier.Equals(Id)))
{
//Create new object of timer, assign identifier =Id,
//set interval and initialize it. add it to collection as
var timer = new DevTimer();
timer.AutoReset = true;
timer.Enabled = true;
timer.Interval = 5000; //miliseconds
timer.Elapsed += timer_Elapsed;
timer.IsInUse=true;
timer.Identifier=Id;
DeviceContainer.timers.Add(timer);
timer.Start();
}
else
{
//Code to stop the existing timer and start it again.
var _timer=DeviceContainer.timers.FirstOrDefault(s=>s.Identifier.Equals(Id))
as DevTimer;
_timer.Stop();
_timer.Start();
}
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
//code that will turn off the device in DB
}
I'm not posting the entire code as that's not the purpose here.
I would use Microsoft's Reactive Framework for this.
Here's the code:
IEnumerable<xxxx> yyyy = new List<xxxx>();
Subject<Unit> clientRequestArrived = new Subject<Unit>();
IDisposable subscription =
clientRequestArrived
.Select(_ => Observable.Interval(TimeSpan.FromSeconds(5.0)))
.Switch()
.Subscribe(_ =>
{
//code to be executed when timer elapses...
//directly access `yyyy` here
});
All you need to do is call clientRequestArrived.OnNext(Unit.Default); every time that a user request comes in and that will be enough for this code to reset the timer.
If you want to stop the timer entirely, just call subscription.Dispose().
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);
Still getting my head wrapped around Timers in C# which are a LOT more powerful than in AS3.
I need to call another method at shorter and shorter intervals. Say once a second in the beginning, then gradually shorter intervals until maybe I am calling the method 100X a second.
I've used coroutines but pretty sure I need an actual Timer object. Can anyone help or point in the right direction?
You can start with this example:
System.Timers.Timer t = new System.Timers.Timer();
public void TimerSetup()
{
t.Interval = 1000;
t.Elapsed += ElapsedMethod;
t.Start();
}
public void ElapsedMethod(object sender, System.Timers.ElapsedEventArgs e)
{
//do stuff
t.Interval = t.Interval - 5; //however much you want it to reduce.
}
You will have to determine the conditions that you need for reducing the timer interval, and when to do it, but this should give you a start.
Using a Task:
shouldIStayInThisLoop = true;
interval = 1000; // 1000 milliseconds == 1 second
Task.Factory.StartNew(()->
{
while (shouldIStayInThisLoop)
{
DoSomeStuff();
if (SomeConditionIsMet())
{
interval = GetNewInterval();
}
Thread.Sleep(interval);
shouldIStayInThisLoop = CheckIfIShouldStayInThisLoop();
}
});
I have an application that uses a timer to 1 in 1 minute perform refresh data in a DataGridView. Depending on the information to return the screen, a different sound will play. Each sound has a playback time. I am using this command to have the effect of duration of my music.
Thread.sleep(GetMusicDuration[i] * 1000);
When I start my application the first time, everything goes well, but when the timer runs TICK event that carries the information in the DataGridView again and run PLAY to play the sounds my Thread.Sleep command does not work, it simply ignores not expect the time set for parameter.
public void PlaySound()
{
try
{
while (1 == 1)
{
List<string> distinctMusic = GetMusicFile.Distinct().ToList();
StopSound();
if (distinctMusic.Count > 0)
{
for (int i = 0; i < distinctMusic.Count; i++)
{
player.SoundLocation = distinctMusic[i];
player.Play();
Thread.Sleep(GetMusicDuration[i] * 1000);
StopSound();
}
}
DisposePlayer();
}
}
catch (Exception e)
{
if (generateLog)
log.LogTxt(e.ToString());
}
}
Until now I did not understand why the exucução wrong.
someone could help me?
thank you...!
Thread.Sleep blocks the UI thread. You should use a timer in stead:
//Create a new timer that ticks every xms
var t = new System.Timers.Timer (GetMusicDuration[i] * 1000);
//When a tick is elapsed
t.Elapsed+=(object sender, System.Timers.ElapsedEventArgs e) =>
{
//what ever you want to do
};
//Start the timer
t.Start();