[C#] Cross-thread operation not valid

0

Witam
Piszę aplikację korzystającą z biblioteki sHGG w Windows Forms w C#.
Mam taki event, który wyświetla wiadomość nadawcy w richTextBoxLog:

public void gadu_GGMessageReceive(object sender, sHGG.MessageReceiveEventArgs args)
        {
                richTextBoxLog.Text = DateTime.Now + "Otrzymałeś wiadomość od numeru " + args.Number + ". Wiadomość:\n" + args.Message;
        }

Jednak po uruchomieniu programu, gdy ktoś wyśle mi wiadomość to wywala błąd:
Cross-thread operation not valid: Control 'richTextBoxLog' accessed from a thread other than the thread it was created on.
Dlaczego tak się dzieje?

0

No bo nie można zmieniać kontrolek z innego wątku niż zostały utworzone. Zrób to poprawnie:

public void UpdateRichTextBox(string text)
{
    if (richTextBoxLog.InvokeRequired)
        richTextBoxLog.Invoke(new Action<string>(UpdateRichTextBox), text);
    else
        richTextBoxLog.Text = text;
}

i wywołuj to podając tekst do podstawienia.

0

Dobra, działa. Dzięki. Głupi błąd :).

0

Wiesz co mała podpowiedź.
else { }

0

Napisałem metodę, która wysyła wiadomość od losowego numeru:

public void SendMessagesToRandomNumber(string message, int from, int to, int ms)
        {
            int liczbaLosowa = 0;
            Random rnd = new Random();
            liczbaLosowa = rnd.Next(from, to + 1);

            gaduBot.GGSendMessage(liczbaLosowa, message);
            richTextBoxLog.Text += "Wiadomość wysłana na numer: " + liczbaLosowa;
            System.Threading.Thread.Sleep(ms);
        }

Stworzyłem przycisk:

private void button1_Click(object sender, EventArgs e)
        {
            button1.Visible = false;
            for (int i = 0; i < 10; ++i )
            {
                SendMessagesToRandomNumber(richTextBoxWiadomosc.Text, int.Parse(textBoxRandomNumberFrom.Text), int.Parse(textBoxRandomNumberTo.Text), int.Parse(textBoxMs.Text));
            }
        }

Jednak mam problem. Po naciśnięciu przycisku cały program zaczyna "mulić" i tylko przez chwilę w richtextboxie pojawia się potwierdzenie wysłania wiadomości. Jestem zmuszony do wyłączenia programu.
Moim zdaniem to "mulenie" powoduje int.Parse. Nie znam innego sposobu na wczytywanie danych typu int z textboxa. Co zrobić żeby program działał sprawnie?

BTW: Nie piszę żadnego bota, po prostu chcę "nauczyć się" programowania.

0

SendMessagesToRandomNumber(richTextBoxWiadomosc.Text, int.Parse(textBoxRandomNumberFrom.Text), int.Parse(textBoxRandomNumberTo.Text), int.Parse(textBoxMs.Text));
Puść to w jakimś wątku oddzielnym, a nie w wątku UI. Ew. jak się nie chcesz bawić to po każdym obrocie pętli daj Application.DoEvents() (ale to niezalecane).
int.Parse na pewno nie jest, tak czasochłonne jak myślisz :), ale inny sposób jest. Convert.ToInt32.

Dobrze, że napisałeś, że nie robisz bota :P

0

Mam następny problem. Nie będę pisał nowego tematu i napiszę tutaj.
Otóż, po wpisaniu w textboxy niepoprawnego numeru GG oraz hasła i naciśnięciu przycisku, którego zadaniem jest połączenie z serwerem dodawany jest do richTextBoxLog.text:

2009-04-24 15:19 - Zalogowano pomyślnie.
2009-04-24 15:19 - Nie zalogowano...
// a powinno tylko pisać "nie zalogowano"

Chciałbym temu zapobiec i wyświetlić stosowny komunikat (np. "Nie można się zalogować, spróbuj ponownie.") oraz przerwać dalszy kod zdarzenia click przycisku buttonPolacz.

Zrobiłem już coś takiego, jednak nie spełnia swojej roli: Utworzyłem nową zmienną bool loginFail = false;, która będzie się zmieniać na true, gdy nie uda się zalogować.
Zdarzenie wygląda tak:

public void gadu_GGLogFailed(object sender, EventArgs args)
        {
            UpdateRichTextBoxLog("Nie zalogowano. Spróbuj ponownie.");
            loginFail = true; // tutaj zmieniam na true
            zalogowano = false;
            button1.Visible = false;
        }

Kod (niecały) zdarzenia Click przycisku buttonPolacz, który służy do połączenia się z serwerem GG:

private void buttonPolacz_Click(object sender, EventArgs e)
        {
            // ...

                if (zalogowano == false)
                {
                    {
                        gadu.GGLogin(serverIP);
                        if (loginFail == true) return;
                        else
                        loginFail = false;
                        zalogowano = true;
                        UpdateRichTextBoxLog("Zalogowano pomyślnie.");

// ...

Co zrobić, by przy niepoprawnym logowaniu wysłało do richTextBoxLog stosowny komunikat oraz przerwało dalszy kod zdarzenia click przycisku buttonPolacz? :

0

Powiem ci, że strasznie dziwnie to robisz. Z tego co zerknąłem przed chwilą w źródła to obok zdarzenia GGLogFailed jest GGLogged i to na nim powinieneś wypisywać, że się udało a nie ustawiać flagę, że się nie udało w zdarzeniu GGLogFailed. Zobacz sobie użycie tej biblioteki np. w wxGadu na Google Code.

0
Deti napisał(a)

Cross-thread operation not valid: Control 'richTextBoxLog' accessed from a thread other than the thread it was created on.

Dziwne... SHGG wywołuje swoje eventy zawsze z wątku "głównego", - a konkretniej - z tego, w którym został utworzony.

Mógłbyś mi wysłać swój kod na [email protected] ? .. Chciałbym zobaczyć ten Cross-thread operation not valid, wg mnie nie powinien wystąpić.

By the way: której wersji SHGG używasz?

Przykro mi, ale kodu już nie mam.
shgg0652

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