Diskuze: Stopky

C# .NET .NET (C# a Visual Basic) Stopky American English version English version

Avatar
thebestgamesify:

čaute , nevie tu niekto naprogramovat niečo take že uživatel len klikne na check box zobrazi sa mu 40minut bolo nastavenych a po 40minutach sa mu ukaže message box 40minut ubehlo ? ?
Ak ano prosim či by to niekto nevedel spravit a poslat sem diky

 
Odpovědět 6. července 17:02
Avatar
Odpovídá na thebestgamesify
Petr Čech (czubehead):

Nikdo to za tebe dělat nebude. Použij Timer nebo vlákno na pozadí.

Nahoru Odpovědět  +1 6. července 17:05
Why so serious? -Joker
Avatar
Petr Stastny
Redaktor
Avatar
Odpovídá na thebestgamesify
Petr Stastny:

Úplně nejjednodušší by bylo po kliknutí na checkbox zobrazit nějaké upozornění, potom uspíš vlákno na 40 minut:

System.Threading.Thread.Sleep(1000*60*40);

a potom zobrazíš další zprávu, že 40 minut uběhlo

 
Nahoru Odpovědět  -4 6. července 17:09
Avatar
Marian Benčat
Redaktor
Avatar
Odpovídá na Petr Stastny
Marian Benčat:

Na první pohled dobrá rada, bohužel s nulovou šancí na úspěch.

Je k tomu plno důvodů.. například tyto:

  1. Všechny UI frameworku (WPF, WebForms) jsou cele pohaneny jedním jediným vláknem a to má na starost nejen logiku, ale i třeba rendering a message bus.. Takže UI mu na 40 minut vytuhne
  2. Co je horší, 40 miut bude zablokované celé toto vlákno, takže se začnou kupit do stacku zpráv zprávy a aplikace zhruba po 5ti minutách spadne na to, že se zahltila tato message bus fronta a on není schopný už recovernout...
  3. Pokud aplikace nebude delší dobu reagovat, windows ji označí jako v deadlocku a označí jako že neodpovídá.

Takže toto řešení je plně špatné. Myšlenka dobrá, bohužžel to takto nepůjde.

Editováno 6. července 22:38
 
Nahoru Odpovědět  +2 6. července 22:38
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

*winforms, swing.. proste cokoliv..

Editováno 6. července 22:42
 
Nahoru Odpovědět 6. července 22:42
Avatar
Odpovídá na Petr Stastny
Ladislav Ondris:

Metoda Sleep by se neměla používat pro běh programu. Je to metoda určená například k testování. Je to uvedeno i v dokumentaci MSDN.

Nahoru Odpovědět  +2 8. července 7:56
Pokud neděláš chyby, nepracuješ na dostatečně těžkých problémech.
Avatar
VitekST
Člen
Avatar
VitekST:

Já bych to osobně vyřešil Timerem, nebo bych si udělal vlákno, kde bych pomocí zmíněné metody čekal X času a pak bych zavolal callback.

Pomocí Timeru:

//Designér - PSEUDOKÓD:
Timer tmrWait; //Deklarace timeru

tmrWait.Interval = 1000*60*40 //Interval timeru
tmrWait.Tick = (metoda) tmrWait_Tick; //Handler události "Tick", zavolá se až uběhne interval

//Následně někde ve třídě:
private void tmrWait_Tick(object o, EventArgs e){ //Metoda, handler události
        MessageBox.Show("Uběhlo."); //Kód handleru
}

Pomocí vlákna:

void Wait(){ //Metoda, která se zavolá, když se má čekat
        Action callback = () => { //Callback
                MessageBox.Show("Uběhlo."); //Kód v callbacku
        };

        Thread waitThread = new Thread(new ThreadStart( () => { //Vlákno
                Thread.Sleep(1000*60*40); //Počkáme 40m
                callback(); //Zavoláme callback
        }));
}

Problém je ten, že v podstatě nemůžeš pozastavit běh programu na nějakém bodě a "ono to bude nějak reagovat", message loop běží ve stejném vlákně jako tvůj kód, jestli ho zamrazíš, aplikace nebude reagovat.

Takže to se musí udělat tak, že to co má být za tím čekáním se umístí do nějaké metody, která se zavolá po určitém čase buďto tím Timerem nebo vláknem.

BTW, dávej si pozor, nemůžeš nijak s formulářem manipulovat (ani s prvky) jestliže se o to snažíš v jiném vlákně než message loop formuláře, vyhodí ti to vyjímku TargetInvocati­onException.

Kód pro manipulaci formuláře musíš spustit ve vlákně s formulářem samotným, použij metodu Invoke (případně BeginInvoke, jestli nechceš čekat na dokončení kódu).

Elegantnější mě ale přijde řešení pomocí vlákna.

Editováno 8. července 17:24
 
Nahoru Odpovědět  +1 8. července 17:22
Avatar
VitekST
Člen
Avatar
Odpovídá na Ladislav Ondris
VitekST:

Nevím, který článek si četl, ale na tomto MSDN článku který jsem vygooglil ( https://msdn.microsoft.com/…ary/d00bd51t(v=vs.110).aspx ) je napsáno něco jiného:

However, we recommend that you use other System.Threading classes such as Mutex, Monitor, EventWaitHandle, or Semaphore instead to sychronize threads or manage resources.

V překladu:

Místo toho ale doporučujeme používat jiné třídy nacházející se v System.Threading, například Mutex, Monitor, EventWaitHandle nebo Semaphore na synchronizaci vláken nebo správu prostředků.

Synchronizaci vláken neprovádíme ani nespravujeme prostředky, nevidím tedy důvod proč ji nepoužít.

 
Nahoru Odpovědět 8. července 17:37
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

NO.. uplne nejjednodušší řešení a nejpochopitelnější pro začítečníka, je prostě pustit BackgroundWorker, na ten čas ho sleepnout a pak v OnCompleted udělat věci na UI. celé se to dá napsat defakto na 4 řádky pomocí lambdy.

 
Nahoru Odpovědět 8. července 21:03
Avatar
Odpovídá na Marian Benčat
Michal Žůrek (misaz):

nejjednodušší pro začátečníka a pak zmíníš lambdy? Hmmm... tak si ne no.

Editováno 8. července 21:44
Nahoru Odpovědět  +1 8. července 21:44
Nesnáším {}, proto se jim vyhýbám.
Avatar
ostrozan
Redaktor
Avatar
ostrozan:

Na časování je časovač - timer
jak vás vůbec může napadnout na 40 minut uspávat cokoliv - ať už jiné vlákno, nebo backgroundWorker?

když jsme u nesmyslů (i když funkčních) přidám ještě jeden

DateTime date = DateTime.Now;

long start = date.Ticks;
long end = start + 24000000000; //24000000000 tiku je 40 minut
while (date.Ticks<end)
{
    date = DateTime.Now;

}
MessageBox.Show("Uběhlo 40 minut");
:-) :-) :-)
 
Nahoru Odpovědět  +1 8. července 22:39
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

busy waiting? jako vazne? Tak ty jsi jinaci master :-) Neuspíš vlákno, což sežere 0 0 výkonu a pak tam napereš busy waiting :-) jdi si lehnout.. to snad ani jako vtip neni dobre :-)

Editováno 11. července 5:02
 
Nahoru Odpovědět  +2 11. července 5:01
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Marian Benčat
ostrozan:

Pravděpodobně nemáš v pět hodin ráno náladu na vtipy :-)
ale k tvé otázce:
ano - myslím to smrtelně vážně - jako příklad toho nejhoršího řešení - absurdity dovedené k dokonalosti, toho,že může existovat ještě něco horšího než pro čekání zakládat vlákno, které má jediné poslání - spát. Nehledě na to, že jak se lze dočíst v dokumentaci tak skutečný čas se od nastaveného liší - a vůbec bych se nedivil, kdyby při požadovaných 40ti minutách byla chyba v řádech minut.

Pokud ale slova

když jsme u nesmyslů (i když funkčních) přidám ještě jeden

málo vystihují co jsem měl na mysli, tak teď to snad pochopíš

Jde o to, že .NET tě nechá spáchat spoustu nelogických konstrukcí a aplikace přitom bude "fungovat", což ale neznamená, že je dobré je používat.

Editováno 11. července 20:20
 
Nahoru Odpovědět  +1 11. července 20:19
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

kdyz nespim, tak ne :D Tak ted tu muzeme rozebrat jak funguji timer a co dela CreateTimerQu­eueTimer

Editováno 12. července 1:55
 
Nahoru Odpovědět 12. července 1:54
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Marian Benčat
ostrozan:

Do až tak akademické diskuse bych nezabředal :-)

ale i tak - zde je mých pět minut práce:

public partial class MainWindow : Window
   {
       DispatcherTimer timer;
       DateTime startTime, stopTime;
       public MainWindow()
       {
           InitializeComponent();
           timer = new DispatcherTimer();
           timer.Interval = TimeSpan.FromMinutes(40);
           timer.Tick += timer_Tick;
       }

       private void button_Click(object sender, RoutedEventArgs e)
       {
           button.Content = "čekej";
           button.IsEnabled = false;
           timer.Start();
           startTime = DateTime.Now;
       }

       void timer_Tick(object sender, EventArgs e)
       {
           stopTime = DateTime.Now;
           timer.Stop();
           TimeSpan ts = stopTime - startTime;
           string str = "Uplynulo " + ts.Minutes.ToString() +" min  " +ts.Seconds.ToString()+" sec  " + ts.Milliseconds.ToString()+" ms";
           MessageBox.Show(str);
           button.Content = "spustit časování";
           button.IsEnabled = true;
       }
   }

není to sice žádný atomový čas - viz obrázek , ale i tak 7 ms na 40ti minutách je myslím slušný výsledek a podle analýzy procesor ani nezaregistroval, že se něco děje

když se ti bude chtít můžeš stejných pět minut věnovat "spícímu vláknu" :-)

 
Nahoru Odpovědět  +1 13. července 16:06
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 15 zpráv z 15.