Witam,
Mam program który co godzinę ma wykonywać coś i tak w nieskończoność, korzystam z https://codinginfinite.com/creating-scheduler-task-seconds-minutes-hours-days/ . Na końcu programu mam Console.ReadKey(); po to consola nie zamykała programu.
Wszystko działa jak należy dopóki nie nacisnę albo nie zaznaczę czegoś w consoli, wtedy program/consola czeka np. na naciśnięcie i blokuje Schedulera więc nie wykonuje się co godzinę, czy jest jakaś możliwość rozwiązania tego problemu?
Scheduler a consola - program blokuje się
- Rejestracja: dni
- Ostatnio: dni
- Postów: 15
- Rejestracja: dni
- Ostatnio: dni
- Postów: 6610
Piotrpi napisał(a):
Na końcu programu mam Console.ReadKey(); po to consola nie zamykała programu.
Wszystko działa jak należy dopóki nie nacisnę albo nie zaznaczę czegoś w consoli, wtedy program/consola czeka np. na naciśnięcie i blokuje Schedulera więc nie wykonuje się co godzinę,
kompletnie nie rozumiem tego opisu - dodaleś ReadKey żeby się nie zamykało i masz problem bo się nie zamyka??
- Rejestracja: dni
- Ostatnio: dni
- Postów: 15
abrakadaber napisał(a):
Piotrpi napisał(a):
Na końcu programu mam Console.ReadKey(); po to consola nie zamykała programu.
Wszystko działa jak należy dopóki nie nacisnę albo nie zaznaczę czegoś w consoli, wtedy program/consola czeka np. na naciśnięcie i blokuje Schedulera więc nie wykonuje się co godzinę,kompletnie nie rozumiem tego opisu - dodaleś
ReadKeyżeby się nie zamykało i masz problem bo się nie zamyka??
Racja trochę chaotycznie :) dodałem kilka ReadKey żeby się nie zamykała aplikacja ale jak przypadkiem nacisnę jakiś klawisz to jakby zatrzymuje się aplikacja. Żeby było łatwiej to zamiast ReadKey powiedzmy że jest Console.ReadLine i wtedy czeka na znak przez co nie wykonuj się to co jest w Scheduler
- Rejestracja: dni
- Ostatnio: dni
- Postów: 342
- Rejestracja: dni
- Ostatnio: dni
- Postów: 10227
A jak zamiast wczytywać znak zrobisz System.Threading.Thread.Sleep(-1)?
- Rejestracja: dni
- Ostatnio: dni
- Postów: 15
Riddle napisał(a):
A jak zamiast wczytywać znak zrobisz
System.Threading.Thread.Sleep(-1)?
Sprawdzałem, nie uruchamia się Scheduler o kolejnej godzinie. Dopiero jak się naciśnie enter to idzie dalej.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 6610
z tego co wiem to żeby scheduler uruchomił zadanie kolejny raz to poprzednie musi się skończyć. Jeśli zadaniem jest odpalenie konsoli to scheduler będzie czekał na zamknięcie konsoli. W jakim celu masz na końcu ReadKey/ReadLine czy cokolwiek innego co blokuje zamknięcie konsoli?
- Rejestracja: dni
- Ostatnio: dni
- Postów: 15
Adin napisał(a):
Widziałem ale niestety mój obecny poziom wiedzy nie pozwala mi tego zastosować
- Rejestracja: dni
- Ostatnio: dni
- Postów: 15
abrakadaber napisał(a):
z tego co wiem to żeby scheduler uruchomił zadanie kolejny raz to poprzednie musi się skończyć. Jeśli zadaniem jest odpalenie konsoli to scheduler będzie czekał na zamknięcie konsoli. W jakim celu masz na końcu
ReadKey/ReadLineczy cokolwiek innego co blokuje zamknięcie konsoli?
To jest aplikacja konsolowa, nie uruchamia innej chyba że ja czegoś nie rozumiem. Na końcu ReadKey/ReadLine mam po to by scheduler co godzine wykonywał kod a bez ReadKey/ReadLine zamknie się automatycznie.
using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Xml;
namespace TaskScheduler
{
class Program
{
static void Main(string[] args)
{
string next_hour_ts = DateTime.Now.AddHours(0).ToString("HH");
int next_hour_ts_int = int.Parse(next_hour_ts);
string next_hour_ts1 = DateTime.Now.AddHours(1).ToString("HH");
int next_hour_ts_int1 = int.Parse(next_hour_ts1);
Console.WriteLine("xxx");
MyScheduler.IntervalInHours(next_hour_ts_int1, 0, 1, //ma uruchamiać się co godzinę w nieskończoność
() => {
Console.WriteLine("xxx");
}
//Console.ReadKey();
System.Threading.Thread.Sleep(-1);
}
}
}
- Rejestracja: dni
- Ostatnio: dni
aa, myślę że wszyscy pomyśleli o windows task schedulerze, a ty używasz po prostu jakiś udziwniony wrapper na timer.
Spróbowałem to odtworzyć u siebie i nie za bardzo mi się udaje - po zaznaczeniu czy wpisaniu czegoś w konsoli nadal timer działa i wykonuje się normalnie.
Pamiętam że faktycznie zaznaczenie w konsoli zazwyczaj powodowało zatrzymanie programu konsolowego, wydaje się że teraz w win11 to poprawili, ewentualnie zależy to od wersji .NET bo w ostatnich wersjach trochę zmieniali z obsługą tasków, nie chce mi się teraz zagłębiać w temat.
Tak czy inaczej możesz użyć asynchronicznych metod konsoli:
public static async Task Main(string[] args)
{
await Console.In.ReadLineAsync();
}
Nie mam jak tego przetestować bo u mnie działa ;)
Jeśli program ma wykonywać coś co godzinę to lepiej żeby zawierał czystą logikę bez żadnego schedulera, timera i blokowania konsoli i wtedy ustawiasz sobie jego odpalanie w windowsowym task schedulerze (harmonogram zadań). To bardziej elastyczne i stabilniejsze rozwiązanie, nie będziesz miał problemów takich jak teraz, czy że ktoś przypadkowo wyłączy program i przestanie się wykonywać w przyszłości, będziesz mógł w dowolnej chwili łatwo zmienić harmonogram, będziesz miał logi kiedy ostatnio został odpalony program i kiedy nastąpi następne uruchomienie, będziesz mógł dodać obsługę błędów i ponowień itp.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 15
obscurity napisał(a):
aa, myślę że wszyscy pomyśleli o windows task schedulerze, a ty używasz po prostu jakiś udziwniony wrapper na timer.
Spróbowałem to odtworzyć u siebie i nie za bardzo mi się udaje - po zaznaczeniu czy wpisaniu czegoś w konsoli nadal timer działa i wykonuje się normalnie.
Pamiętam że faktycznie zaznaczenie w konsoli zazwyczaj powodowało zatrzymanie programu konsolowego, wydaje się że teraz w win11 to poprawili, ewentualnie zależy to od wersji .NET bo w ostatnich wersjach trochę zmieniali z obsługą tasków, nie chce mi się teraz zagłębiać w temat.Tak czy inaczej możesz użyć asynchronicznych metod konsoli:
public static async Task Main(string[] args) { await Console.In.ReadLineAsync(); }Nie mam jak tego przetestować bo u mnie działa ;)
Jeśli program ma wykonywać coś co godzinę to lepiej żeby zawierał czystą logikę bez żadnego schedulera, timera i blokowania konsoli i wtedy ustawiasz sobie jego odpalanie w windowsowym task schedulerze (harmonogram zadań). To bardziej elastyczne i stabilniejsze rozwiązanie, nie będziesz miał problemów takich jak teraz, czy że ktoś przypadkowo wyłączy program i przestanie się wykonywać w przyszłości, będziesz mógł w dowolnej chwili łatwo zmienić harmonogram, będziesz miał logi kiedy ostatnio został odpalony program i kiedy nastąpi następne uruchomienie, będziesz mógł dodać obsługę błędów i ponowień itp.
await Console.In.ReadLineAsync(); działa nieco lepiej bo nie zatrzymuje się po wpisaniu czegoś ale jeśli zaznaczy się coś w konsoli(wtedy obok loga aplikacji w lewym górnym rogu w tej belce pojawia sie "wybierz:") to niestety blokuje wykonanie schedulera.
Nie mogę zmniejszyć .NET bo using System.IO.Ports; wymaga wersji 6.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: warszawa
- Postów: 315
To co musisz zrobić to napisać petle while(true) i dodać thread sleepa co na minute. I co te minute sprawdzasz czy godzina juz mineła, jezli tak to robisz co masz do zrobienia.
Jeden level wyzej to samo, tylko na timerze.
A jeszcze jeden level wyżej to ustawienie aplikacji żeby była ustawiana nie w spasku a w tle. Jak antywiurus lub drukarka, ale to jest upierdliwe.
- Rejestracja: dni
- Ostatnio: dni
Piotrpi napisał(a):
ale jeśli zaznaczy się coś w konsoli(wtedy obok loga aplikacji w lewym górnym rogu w tej belce pojawia sie "wybierz:") to niestety blokuje wykonanie schedulera.
No tak faktycznie było w starych windowsach, w win11 już tak nie jest w domyślnym terminalu, trzeba ręcznie odpalić conhost żeby tak było.
Zauważ że w przypadku użycia async to tylko widok konsoli jest zapauzowany, program jest nadal wykonywany i "zaległe" wiadomości pojawiają się w konsoli po jej odpauzowaniu. Myślę że nic więcej się już nie da zrobić.
Nadal polecam przejście na harmonogram zadań do tego celu.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 15
We właściwościach konsoli wyłączyłem "Tryb szybkiej edycji" i nie da się już nic zaznaczyć a to rozwiązuje już problem. To raczej nie starych Windowsach bo ja mam W10.
_flamingAccount napisał(a):
To co musisz zrobić to napisać petle while(true) i dodać thread sleepa co na minute. I co te minute sprawdzasz czy godzina juz mineła, jezli tak to robisz co masz do zrobienia.
Jeden level wyzej to samo, tylko na timerze.
Kod ma się wykonywać o równych godzinach a to powyżej chyba by tak nie zadziałało. Tak czy inaczej prymitywnie ale mam to co chciałem
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: warszawa
- Postów: 315
Kod ma się wykonywać o równych godzinach a to powyżej chyba by tak nie zadziałało. Tak czy inaczej prymitywnie ale mam to co chciałem
2 rzeczy. 1) oczywiście ze by działało tylko zamiast co minute, po piwrszym sprawdzeniu ustawiasz na brakujacy czas, a potem na 59.999 min. Na windowsie i konsoli i tak nie masz co liczyczyć na nic dokładniejszego nie 16 ms. wiec to dobre rozwiazanie, i 2? linie kodu.
2 ) masz to co chciałeś super. Którego rozwiazania użyłeś?
- Rejestracja: dni
- Ostatnio: dni
- Postów: 15
Rozwiązanie await Console.In.ReadLineAsync(); i wyłączenie "Trybu szybkiej edycji":
https://iditect.com/faq/csharp/how-to-programmatic-disable-c-console-application39s-quick-edit-mode.html