IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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
Petr Vít
Člen
Avatar
Petr Vít:27.2.2018 21:48

Zdravím,

používám WPF a když z hlavní třídy zavolam funkci obsahujicí následný kód tak cele WPF zamrzne.

public void zkouska()
      {
          int e = 1;
          bool pravda = true;
          while (pravda)
          {

              e++;
              Thread.Sleep(1000);
              mainWindow.textBox1.Text += e + "\r\n";
          }

      }

Víte čím to může být ?

Díky

 
Odpovědět
27.2.2018 21:48
Avatar
d4rkw34v3r
Tvůrce
Avatar
Odpovídá na Petr Vít
d4rkw34v3r:27.2.2018 21:56

Protože tím nekonečným cyklem zasekneš UI vlákno =)) nejdřív vyřeš konečnost toho cyklu
a ten kód prováděj na pracovním vlákně

 
Nahoru Odpovědět
27.2.2018 21:56
Avatar
Petr Vít
Člen
Avatar
Petr Vít:27.2.2018 22:03

No chtel jsem docilit toho ze po stisku jednoho tlacitka se spusti tahle smycka.
A inicialzace bool pravda, bude mimo smycku. Nejak takhle

bool pravda = true;

public void zkouska()
      {
          int e = 1
          while (pravda)
          {

              e++;
              Thread.Sleep(1000);
              mainWindow.textBox1.Text += e + "\r\n";
          }
 }

A pak jine tlacitko nastavi bool na false. A tim by se smycka ukoncila.

Nesmysl?

Editováno 27.2.2018 22:04
 
Nahoru Odpovědět
27.2.2018 22:03
Avatar
Petr Vít
Člen
Avatar
Petr Vít:27.2.2018 22:28

Ted to bude asi trosku offtopic, ale kdyz zkusim vytvorit objekt noveho vlakna na tuto funkci, tak mi to vypise ze musi byt staticka. Kdyz ale zmenim funkci na statickou nemuzu z ni volat objekt z jine tridy. Je na to nejake reseni?

Diky

 
Nahoru Odpovědět
27.2.2018 22:28
Avatar
Odpovídá na Petr Vít
Marian Benčat:27.2.2018 23:15

Mám chvilku čas a tak ti prozradím jak všechny rozumné UI frameworky pracují (proto třeba React Native funguje jinak).

  1. Všechny rozumné UI frameworky používají 1 thread - 1 vlákno, tzv. Single Thread Apartment, protože je to strašně výhodné.
  2. V tom threadu je jakási smyčka, která funguje HODNĚ ZJEDNODUŠENĚ takto:
while(app.NotEnd) {
   var work = tasks.deque(); // vytahne si z fronty nějaký úkol - callback
   tasks.do();
}
  1. Do te fronty vkladaji ty ukolyl nejruznejsi strany
    • třeba "operační systém", tam vkládá vnější zprávy - vstup z klávesnice, pohyb myši atd...
    • nebo ty, když na nějaký event přidáš event handler...
    • nebo framework - třeba práci "Repaint()" která má přerenderovat grafiku
    • nebo tam můžeš vložit něco ručně sám přes nějakého "prostředníka"
  2. Všechno z pracovává to jedno vlákno.. když tzv. rozepíšu tu iteraci toho While cyklu tak se tam děje toto:
 while(1) {
var work = tasks.dequeu(); // zde se vybere ten tvuj task - ten NIKDY NESKONCI, protoez tam mas while(true);
Repaint();  // sem se to nikdy nedostane.
}

proto ti zatuhne celá aplikace.. ten tvůj uko lse nikdy nedokončí a on nemůže skočit na další...

  1. Navíc.. jak jsem již napsal, do té fronty může vkládat i někdo jiný - třeba operační systém... takže pokud to ve svém vlákně zacyklíš, tak se ti stane i to, že se ta fronta "přeplní" a aplikace ti celá lehne na chybu, že neze do té fronty umístit další message..
Nahoru Odpovědět
27.2.2018 23:15
Totalitní admini..
Avatar
Petr Vít
Člen
Avatar
Petr Vít:27.2.2018 23:32

Chápu, díky za vysvetleni.
Ackoliv teda trosku nerozumim tomu ze v konzolove aplikaci muzu pres thread volat "nestaticke" funkce . Tak ve WPF jdou pres thread volat jen staticke funkce. To je tam proc? A jak tedy ve WPF volat thready?

Samozrejme se nabizi moznost z ni statickou udelat ale to ovsem z te funkce zase nemuzu volat jine objekty.

 
Nahoru Odpovědět
27.2.2018 23:32
Avatar
Odpovídá na Petr Vít
Marian Benčat:27.2.2018 23:45

Nechápu tě. Asi máš na mysli to, že nemůžeš měnit instance, co jsou vytvořené main threadem, protože ti to zařve, že šaháš na něco z jiného threaud, než kterým to bylo vytvořeno.

Musíš takto:

Application.Current.Dispatcher.BeginInvoke(
  DispatcherPriority.Background,
  new Action(() => this.buttonek.Properta = 50));

tj. musíš to posílat přes dispatchera.

Nahoru Odpovědět
27.2.2018 23:45
Totalitní admini..
Avatar
Odpovídá na Petr Vít
Marian Benčat:27.2.2018 23:46

jinak konzole není single thread apartment, proto ti dovolí měnit z jakéhokoliv threadu, jakékoliv věci - a ne, nedělej to, určitě nevíš jak to synchronizovat a neznáš poměrně hodně obtížnou C# volatilnost.

Nahoru Odpovědět
27.2.2018 23:46
Totalitní admini..
Avatar
Petr Vít
Člen
Avatar
Petr Vít:28.2.2018 8:34

Dispatcher si teda musim nastudovat. U me to hazi nasledujici problem :

 
Nahoru Odpovědět
28.2.2018 8:34
Avatar
Odpovídá na Petr Vít
Marian Benčat:28.2.2018 9:42

No to nesouvisi s tím co jsem psal.. to souvisí s tím,. že thread chce lambdu jako popis tasku.. tj. statickou metodu.

Nahoru Odpovědět
28.2.2018 9:42
Totalitní admini..
Avatar
Petr Vít
Člen
Avatar
Petr Vít:28.2.2018 11:25

Jenze pokud z toho udelam statickou metodu. Tak nemuzu volat pres "mainWindow" objekt textbox1.. Respektive nemuzu pres to volat objekty z hlavní třídy.

 
Nahoru Odpovědět
28.2.2018 11:25
Avatar
Odpovídá na Petr Vít
Michal Štěpánek:28.2.2018 12:15

Nevím, jestli dostatečně chápu, čeho chceš dosáhnout. Nicméně v tvém prvním příspěvku máš nějaký nekonečný cyklus. Nelze ho spouštět v hlavním vlákně (to už jsi zjistil). Práce s vlákny není úplně jednoduchá záležitost, protože mezi vlákny musíš páchat synchronizaci, abys dosáhl toho, co potřebuješ. Zkus se podívat na komponentu "backgroundworker", pomocí které se dají celkem jednoduš spouštět akce v jiném vlákně na pozadí a synchronizovat s hlavním vláknem...

Editováno 28.2.2018 12:17
Nahoru Odpovědět
28.2.2018 12:15
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Petr Vít
ostrozan:28.2.2018 13:59

No já zírám - ještě nedávno jsi neměl tušení o cyklu while a teď se s ním nemůžeš rozloučit - navíc jsi za těch pár dní pokročill až k vláknům - jsi nejspíš génius :)

ale spíš ne,takže buď máš nějaké konkrétní zadání, tak se poděl co by to mělo dělat
a nebo prostě experimentuješ jen tak - ale bez znalosti základů stejně nikdy nepochopíš co se ti tu všichni snaží vysvětlit - takže začni pěkně od začátku
tipuju totiž že z toho, co třeba píše Marian Benčat rozumíš tak každé druhé slovo

 
Nahoru Odpovědět
28.2.2018 13:59
Avatar
Odpovídá na Michal Štěpánek
Erik Šťastný:28.2.2018 14:04

Osobně mi přijde ještě jednodušší Async Task v dnešní době .NETu 4.5+ na spouštění akcí, které by blokovali GUI

 
Nahoru Odpovědět
28.2.2018 14:04
Avatar
Petr Vít
Člen
Avatar
Petr Vít:28.2.2018 14:25

O cyklu while mám tušení již dlouho. Ale chtěl jsem nějaké efektivnější řešení. To je vse... Ano mam konkretni vizi a ucim se na konkretních situacích.

Zkusím tedy nazorne popsat jakou mam predstavu:

WPF Aplikace - dve tlacitka START a STOP. Jednim spoustim a druhym zastavuji cyklus sekundarni tride.

viz obrazek.

Diky

Editováno 28.2.2018 14:27
 
Nahoru Odpovědět
28.2.2018 14:25
Avatar
ostrozan
Tvůrce
Avatar
ostrozan:28.2.2018 17:37

OK, takže jsme nedozvěděli nic nového - asi je to tajné

takže tady máš funkční příklad dvou počítadel, z nichž jedno běží na hlavním vlákně a druhé jako asynchronní úloha a kterou můžeš, podle svého požadavku spouštět a zastavovat tlačítkama

public partial class MainWindow : Window
{
    bool runAsyncPocitadlo;
    long cnt = 0;
    long cnt1 = 0;
    DispatcherTimer timer = new DispatcherTimer();

    public MainWindow()
    {
        InitializeComponent();
        timer.Interval = TimeSpan.FromMilliseconds(100);
        timer.Start();
        timer.Tick += Timer_Tick;
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        tblock2.Text = cnt++.ToString();
    }

    private async Task AsynchronniPocitalo()
    {
        runAsyncPocitadlo = true;
        while (runAsyncPocitadlo)
        {
            tblock.Text = cnt1.ToString();
            cnt1++;
            await Task.Run(() => Thread.Sleep(500));
        }
    }

    private async void btnZap_Click(object sender, RoutedEventArgs e)
    {
        await AsynchronniPocitalo();
    }

    private void btnVyp_Click(object sender, RoutedEventArgs e)
    {
        runAsyncPocitadlo = false;
    }
}
 
Nahoru Odpovědět
28.2.2018 17:37
Avatar
Petr Vít
Člen
Avatar
Petr Vít:28.2.2018 23:12

Tak vyresno. Chci Vam vsem podekovat za reseni. A taky uzivateli d4rkw34v3r.

Nakonec jsem to udelal pres asynchronni programovani jak jste poradily.

public bool pravda = true;
        public async void Alda()
        {
            int e = 1;

                while(pravda)
            {
                mainWindow.textBox1.Text += " " + e + "\r\n";
                e++;
                await Task.Delay(1000);
            }

        }

a buttony

private void tridaButton_Click(object sender, RoutedEventArgs e)
       {
           cles.pravda = true;
           cles.Alda();        }


private void Button_Click(object sender, RoutedEventArgs e)
       {

           cles.pravda = false;
       }
Editováno 28.2.2018 23:13
 
Nahoru Odpovědět
28.2.2018 23:12
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 17 zpráv z 17.