Diskuze: While - freez WPF.
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 17 zpráv z 17.
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
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ě
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?
Mám chvilku čas a tak ti prozradím jak všechny rozumné UI frameworky pracují (proto třeba React Native funguje jinak).
while(app.NotEnd) {
var work = tasks.deque(); // vytahne si z fronty nějaký úkol - callback
tasks.do();
}
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ší...
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.
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.
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.
No to nesouvisi s tím co jsem psal.. to souvisí s tím,. že thread chce lambdu jako popis tasku.. tj. statickou metodu.
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...
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
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
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
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;
}
}
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;
}
Zobrazeno 17 zpráv z 17.