Synchronizacja wątków - jak?

0

Witam. Mam formatkę a na niej button i label. Po kliknięciu w button uruchamiany jest nowy wątek a w nim metoda która pisze coś w labelu. Jak zsynchronizować wątek GUI z nowym wątkiem?

private void button1_Click(object sender, EventArgs e)
        {
            new Thread(new ThreadStart(Oblicz)).Start();
        }
        void Oblicz()
        {
            label1.Text = "wynik";
        }

Ciekawi mnie to bo natknąłem się na metodę WebClient.DownlaodFileAsync() która nie blokuje wątku wywołującego i można swobodnie wyświetlać wyniki jej działania na formie. Próbowałem zrobić coś podobnego, kombinowałem z klasami Monitor i Mutex ale za nic tego nie ogarniam :/ Proszę o pomoc jak to zrobić, z góry dzięki pozdro

0

Invoke

0

"jezeli chodzi TYLKO o uzywanie kontrolek stworzonych w innym wątku"

nie wiem czy to jest najbardziej poprawna metoda ale można na przykład tak:
tworzysz delegacje.
wskazujesz na metoda ktora pisze cos w labelu
a potem jak kolega wyżej napisał używasz inovke w nowym wątku
this.invoke(delagacja) i już.

przyklad, choc pewnie inaczej da sie to zrobic na pewno.

public delegate void metoda(string napis); //delegacja

        private void button1_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(writing);
            t.Start();
        }
        void writing()
        {
            int x = 0;
            metoda m = new metoda(wypisz_w_label);
            while (true)
            {
                x++;
                Thread.Sleep(100);
                this.Invoke(m,x.ToString());
            }
        }

        void wypisz_w_label(string napis)
        {
            label1.Text = napis;
        }


0

W tym przypadku najprosciej użyc BackgroundWorker-a

0

Chyba się nie rozumiemy :-P Ja wiem że można to zrobić z użyciem metody Invoke() i delegata... Ale mi chodzi o coś innego :-P Proponuję przyjrzeć się opisowi wspomnianej przeze mnie metody WebClient.DownloadFileAsync() - "Downloads, to a local file, the resource with the specified URI. This method does not block the calling thread." Można wyświetlać na formie (np. w labelu) postęp pobierania pliku BEZ UŻYCIA DELEGATÓW i nie wywala przy tym żadnego wyjątku cross-thread operation. Wygląda to mniej więcej tak:

        private void button1_Click(object sender, EventArgs e)
        {
            WebClient webclient = new WebClient();
            webclient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webclient_DownloadProgressChanged);
            webclient.DownloadFileAsync(new Uri("plik w sieci web"), @"C:\plik lokalny");
        }

        void webclient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            label1.Text = e.ProgressPercentage.ToString();
        }

I właśnie zastanawia mnie jak to działa... :-P Pomyślałem że wykorzystano tutaj synchronizację wątków, ale nie mam pojęcia jak samemu się za to zabrać... Jeśli ktoś mógłby pokazać jakiś przykładowy kod źródłowy to byłbym bardzo wdzięczny :-)

0

No toć mówię, masz BackgroundWorker i tam tez jest event ProgressChanged. Czego ci trzeba więcej?

Jeżeli pytasz jak to jest zrobione w webcliencie, to jest oddzielny wątek, z niego wysłany event do twojego wątku (ty akurat uzywasz eventu DownloadProgressChanged) w taki sposób, aby event wykonał się już w głównym wątku, a nie pobocznym. Czyli podobnie jak ma BackgroundWorker.

Jak to zrobić samemu od zera - poszukaj, była nie tak dawno dyskusja o tym na forum, nie chce mi sie szukac. Samo delaget i invoke do tego nie wystarczy, to jest (nieco) bardziej skomplikowane.

1 użytkowników online, w tym zalogowanych: 0, gości: 1