Jak uśpić wątek na 2 sekundy?

Odpowiedz Nowy wątek
2017-11-16 19:03
0

Witam chciałbym wczytywać dane po linijce co 2 sekundy do listboxa.

 public void SaveDataToListbox()
        {
            StreamReader sr = new StreamReader(@"C:\\test\\programTv.txt");
 
            string line;
 
            while ((line = sr.ReadLine()) != null)
            {
                Thread.Sleep(2000);
                listBox1.Items.Add(line);
 
            }
        }

Podany powyżej kod zatrzymuje aplikację a w listboxie nie wyświetlają się żadne dane. Z góry dziękuję za pomoc.

edytowany 2x, ostatnio: furious programming, 2017-11-16 19:45

Pozostało 580 znaków

2017-11-16 20:29

No to tak:
Po pierwsze nie możesz usypiać głównego wątku, bo aplikacja Ci się zawiesi, więc aby wywołać ten Twój kod musisz utworzyć nowy wątek.
Po drugie jak już utworzysz nowy wątek i w nim będziesz korzystał z kontrolek to musisz ten kod przekierować do tego wątku głównego, są różne sposoby, ja użyłem obiektu SynchronizationContext, możesz sobie poczytać o powinowadztwie do wątku.
Po trzecie poczytaj sobie o zwalnianiu zasobów, interfejsie IDisposable i metodzie Dispose, bo nie sprzątasz po wykonaniu operacji na pliku.
No i jak używasz znaku "@" to nie musisz dodawać ukośnika przed ukośnikiem, małpa zapewnia to, że ten string zostanie w takiej postaci jak jest

Tutaj Twój kod przerobiony tak, żeby działał:

    private void button1_Click(object sender, EventArgs e)
        {
            SynchronizationContext sc = SynchronizationContext.Current;
            Task.Factory.StartNew(() =>
            {
                using (StreamReader sr = new StreamReader(@"C:\test\programTv.txt"))
                {
                    string line;
 
                    while ((line = sr.ReadLine()) != null)
                    {
                        string tmpStr = line;
                        Thread.Sleep(2000);
                        sc.Post((obj)=>listBox1.Items.Add(tmpStr),null);
                    }
                }                 
            });
        }
Mam jeszcze jedno pytanie jak przejdzie do końca pętla po wszystkich liniach w pliku, to wyświetla mi się błąd "Wartość nie może być zerowa" w linijce gdzie dodaje dane do listboxa. Wiesz może jak ten błąd rozwiązać? Wszystkie dane się wczytają do listboxa i na końcu jest ten błąd. - erbon24 2017-11-16 21:10
Problem rozwiązałem zamieniając "post" na "send". Już wszystko działa. - erbon24 2017-11-16 21:18
@erbon24: pytania na temat zadawaj w postach. - furious programming 2017-11-17 00:44
Przy użyciu Post na pewno jedna wartość jest nie wczytana, sprawdź to sobie jeszcze raz. Czemu? Bo na końcu tak jak piszesz wykonuje jeszcze jedną operację listBox add i wywala błąd czyli chce dodać nulla do tego listBoxa. Jak chcesz wiedzieć coś więcej na ten temat to musiałbyś sobie poczytać o wyrażeniach lambda w wątkach. - Manuel.Artificer 2017-11-17 00:49

Pozostało 580 znaków

2017-11-16 23:57
0

Nie używaj Send tylko Post. Metoda Post nie czeka na zakończenie wykonywanych operacji, a Send tak i blokuje wątek roboczy, czyli wstrzymuje działanie wątku do czasu dodania tego stringa do listBoxa (wykonania instrukcji z metody Post w głównym wątku). No i takie coś niesie za sobą ryzyko zakleszczenia.

A błąd wywala Ci dlatego, że usunąłeś linijkę

string tmpStr = line;

Nie bez powodu była w tej pętli. Po prostu musisz utworzyć kopię tej wartości.

Pozostało 580 znaków

2017-11-17 11:13
2

Ale po co tak kombinować? Przecież to można dużo prościej zrobić:

private async void button1_Click(object sender, EventArgs e)
{
    string[] fileContent = File.ReadAllLines(@"C:\test\programTv.txt");
 
    foreach(string s in fileContent)
    {
        listBox1.Items.Add(s);
        await Task.Delay(2000);
    }
}

Zauważ, że metoda button1_Click została wyposażona w słowo async. Dzięki czemu można w tej metodzie używać wywołań asynchronicznych.
W pierwszej linijce otwieram plik i jego zawartość ląduje w tablicy stringów.

Następnie jest prosta pętla, w której dodajemy poszczególne elementy do ListBoxa.
Task.Delay powoduje wstrzymanie tej pętli na 2 sekundy. Można tego użyć w taki sposób dzięki async/await. Ich użycie oddelegowuje zadanie do osobnego wątku, dzięki czemu nie wstrzymujemy głównego wątku aplikacji.

Dobrze jest też na początku tej metody (Click) zdeaktywować guzik: button.Enabled = false, a na końcu z powrotem go aktywować. Dzięki temu nie klikniesz w niego podczas już zaczętej operacji.

Pozostało 580 znaków

2017-11-17 11:24
0

No można, ja jedynie przerobiłem jego kod, żeby działał. Może ma taką potrzebę, żeby wczytywać linijka po linijce. Jeżeli miałby strasznie długi plik to ładowanie wszystkiego do pamięci może trochę zająć, a tak to będzie miał wyświetlane od razu.

Pozostało 580 znaków

2017-11-20 10:45
0

To to samo można osiągnąć wywołując File.ReadLines w pętli foreach :)

Pozostało 580 znaków

2017-11-20 14:17
0

Tego tam właśnie brakowało. A co do kodu napisanego przeze mnie no to ja staram się nie robić zbytnio zmian w tym co ktoś już napisał. Dlaczego? No bo jak mu przerobisz cały kod, a on jest świeżakiem to może być mu ciężko go zrozumieć. A tak dodajesz nowe instrukcje oczywiście z komentarzem do czego to służy. Dodatkowo jak możesz zauważyć nie sprzątał po użyciu pliku, więc chciałem mu pokazać co musi zrobić, żeby było poprawnie. Najpierw trzeba zapoznać się z podstawami, a potem można pracować nad poprawą i upiększaniem kodu.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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