Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Tayson
Člen
Avatar
Tayson:10.12.2013 15:31

Zdravim

Neviem teraz akym smerom sa uberat tak poprosim o radu. Mam nejaky form1 kde ak kliknem na tlacidlo tak sa ten form skryje a otvori sa form2. V tomto forme2 mam tlacidlo ktore vola metodu z triedy. Trieda sa vola test. Takze som si vytvoril objekt vo form2 na triedu test a volam si nasledujucu metodu :

public void create_thread_sd()
{
Thread thread = new Thread(alarm_sd);
list_thread.Ad­d(thread);
thread.Start();
}

Tu sa vlastne vytvori vlakno a vo vlakne sa spusta nasledujuca metoda:

private void alarm_sd()
{
while(!work)
{
if(communicati­on.receivedStrin­g.Contains("SD CARD status 0"))
{
tb1.Invoke((Met­hodInvoker)de­legate()
{
tb1.AppendTex­t("OK");
});
t1.Suspend();
work = true;
}
}
work = false;
}

Ako ste si mohli vsimnut tak si ukladam to vlakno do Listu<>. Vsetko funguje az na to ze ak chcem zatvorit form2 a znova otvorit form1 tak mam spustene vlakno alebo viacero vlakien tak ich potrebujem abornut .... skusal som aj pri ukoncovani form2 ked kliknem na nejake tlacidlo dat prechadzat List<> a ku kazdemu vysledku dat abort() ale nefunguje to ... neda sa nejako pri zatvrani form2 killnut vlakna ktore su v nom spustene ?

 
Odpovědět
10.12.2013 15:31
Avatar
Juraj Mlich
Tvůrce
Avatar
Juraj Mlich:10.12.2013 15:55

Skús používať tlačítko Vložiť zdrojový kód. Takto sa to zle číta :)

 
Nahoru Odpovědět
10.12.2013 15:55
Avatar
coells
Tvůrce
Avatar
Odpovídá na Tayson
coells:10.12.2013 16:09

Thread.Abort() vyvolá ve vlákně výjimku ThreadAbortEx­ception a vlákno se tak může ukončit. Tvůj problém bude někde jinde.

  1. nechápu, proč voláš Thread.Suspend()?
  2. abort vlákna skončí s nedefinovanou hodnotou "work"
  3. Dispatcher.Invoke() může potlačit TheadAbortException

Obecně by takovýhle kód měl fungovat:

class Form
{
  volatile bool work = false;
  Thread thread = null;

  private void alarm_sd()
  {
    while (!work) { ... }
  }

  public void create_thread_sd()
  {
    this.work = true;
    this.thread = new Thread(alarm_sd);
    this.thread.Start();
  }

  public void kill_thread()
  {
    this.work = true;
    this.thread.Abort();
    this.thread.Join();
    this.thread = null;
  }
}

Pokud nerozumíš, co dělá metoda kill_thread(), pak si nastuduj tenhle článek: http://www.albahari.com/threading/

Jinak v tomhle kousku kódu vidím hned další chybu. Asi bys vlákna neměl používat, Timer by byl výhodnější.

 
Nahoru Odpovědět
10.12.2013 16:09
Avatar
Tayson
Člen
Avatar
Tayson:10.12.2013 19:48

Rozumiem tej tvojej metode kill_thread().... vlastne premennu work nastavis na true abortnes vlakno a pockas kym sa dokonci ale nechapem preco potom das thread=null ....a tamto t1.suspend() si nevsimaj vobec sa to netyka tohto... nemyslim si ze timer by bol vhodnejsi .... ide o to ze vo vlakne sa stale vykonava cyklus while a ja to nasilne potom abortnem

 
Nahoru Odpovědět
10.12.2013 19:48
Avatar
coells
Tvůrce
Avatar
Odpovídá na Tayson
coells:10.12.2013 22:04

Referenci na thread nastavuji na null, aby se mohla uvolnit paměť přes garbage collector. To je důležité kvůli unmanaged paměti, kterou ta instance drží.

Abort vlákna slouží právě k tomu, abys přerušil cyklus, který se přerušit nechce, v tom není problém. Případně můžeš jen nastavit work=false a zavolat Join().

Problém je v tom, že tam máš zaručeně thread-conditions a kód čas od času nebude fungovat. Pokud communication­.receivedString tedy není synchronizované někde uvnitř.

Timer je výhodnější z jediného důvodu - kdykoliv nemusíš pracovat s vlákny, je to výhodnější! Tohle vlákno ti vytíží procesor na 100% a nebude k tomu důvod. Pro komunikaci s IO se používají async události přes thread-pool a synchronizační primitiva typu ResetEvent nebo Semaphore.

Správný scénář by měl být takový, že když aplikace načte vstup z IO zařízení, vyvolá ManualResetEvent událost, na kterou je pověšené tohle vlákno. Po zpracování vlákno resetuje ManualResetEvent a pověsí se na WaitHandle. Takže nakonec vlákno nic nedělá, dokud nepřijde něco z IO, pak to zpracuje a zase spí.

 
Nahoru Odpovědět
10.12.2013 22:04
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 5 zpráv z 5.