Scheduler a consola - program blokuje się

Scheduler a consola - program blokuje się
PI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
0

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?

abrakadaber
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6610
1
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??

PI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
0
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

Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
0

A jak zamiast wczytywać znak zrobisz System.Threading.Thread.Sleep(-1)?

PI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
0
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.

abrakadaber
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6610
0

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?

PI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
PI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
0
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/ReadLine czy 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.

Kopiuj
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);

        }
    }
}
obscurity
  • Rejestracja: dni
  • Ostatnio: dni
1

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:

Kopiuj
        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.

PI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
0
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:

Kopiuj
        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.

FA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: warszawa
  • Postów: 315
0

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.

obscurity
  • Rejestracja: dni
  • Ostatnio: dni
0
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.

PI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
0

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 😀

FA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: warszawa
  • Postów: 315
0

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ś?

PI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
1

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

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5227
0

imo to lepszy byłby plik z logami + brak wyskakującej konsoli

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.