Diskuze: Stopky
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 15 zpráv z 15.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Nikdo to za tebe dělat nebude. Použij Timer nebo vlákno na pozadí.
Ú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
Na první pohled dobrá rada, bohužel s nulovou šancí na úspěch.
Je k tomu plno důvodů.. například tyto:
Takže toto řešení je plně špatné. Myšlenka dobrá, bohužžel to takto nepůjde.
*winforms, swing.. proste cokoliv..
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.
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 TargetInvocationException.
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.
Nevím, který článek si četl, ale na tomto MSDN článku který jsem vygooglil ( https://msdn.microsoft.com/…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.
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.
nejjednodušší pro začátečníka a pak zmíníš lambdy? Hmmm... tak si ne no.
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");
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
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.
kdyz nespim, tak ne Tak ted tu muzeme rozebrat jak funguji timer a co dela CreateTimerQueueTimer
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"
Zobrazeno 15 zpráv z 15.