Wielowątkowść nie odcina formy

0

Witam. Chciałbym się was zapytać jak tą wielowątkowość zrobić. Napisałem programik do sprawdzenia przy wysyłaniu requestów co sekundę non stop i dodałem taki kod dla odświeżania labela na formie
a - inkrementacja pętli, w której jest też request

                this.Invoke(new MethodInvoker(delegate()
                    {
                        getA = a;
                        label1.Text = getA.ToString();
                    }));

Mimo tego, że taki kod jest dodany do odświeżania labela to przy spamowaniu requestami forma jest zacięta nadal, odcina się dopiero co jakiś czas. Jak mogę to zrobić tak aby requesty latały jak szalone a label odświeżał się bez względu na requesty? Z góry dzięki!

0

pokaż to "wysyłanie requestów co sekundę non stop".

0
public void abc(int size)
{
    for(int a = 0; a < size; a++)
    {
     //request
    }
}
0

no a jak tworzysz nowy wątek?

0
public void abc(int size)
{
    for(int a = 0; a < size; a++)
    {
     this.Invoke(new MethodInvoker(delegate()
                    {
                        getA = a;
                        label1.Text = getA.ToString();
                    }));
        //dalej request
    }
}
0

widze, ze nie masz pojecia co to watki. lepiej poczytaj na google

0

Panu .Al chodziło o to że jak wywołujesz metodę ABC to powinieneś to wykonać z innego wątku inaczej forma ciągle będzie blokowana ponieważ będzie wykonywał to wątk Dispatchera. Czy wykonujesz tą operacje w taki sposób ? Jeżeli tak to pokaż kod , jeżeli nie to dopisz ten kod.

0

W ten sposób? Wywołuje metode abc (z innego wątku)?

        private void button1_Click(object sender, EventArgs e)
        {
            this.Invoke(new MethodInvoker(delegate()
                {
                    abc();
                }));
        }

        public void abc()
        {
            //pętla i request
        }
0

Nie.

Poczytaj do czego służy Invoke, a jak chcesz coś robić na wątkach to o TPL.

0

Tak spróbuj:

private void button1_Click(object sender, EventArgs e)
{
	ThreadPool.QueueUserWorkItem(delegate { this.abc(); });
}

public void abc()
{
	App.Current.Dispatcher.BeginInvoke(new Action(() => {
		for(int a = 0; a < size; a++)
		{
			getA = a;
			label1.Text = getA.ToString();
		}
	}));
}

Krótko: odpalasz metode this.abc() jako wątek w puli wątków. Wewnątrz tej metody pętla dotyka GUI więc musisz skorzystać z Dispatcher'a oraz BeginInvoke żeby GUI było aktualizowane. Każde kliknięcie przycisku odpala nowy wątek. o to chodziło? Tak nawiasem mówiąc to co się dzieje w Twojej pętli jest trochę bez sensu, bo nawet nie zdążysz zobaczyć zawartości label1.Text ale...

Reasumując:

// Tworzenie wątku, a raczek skorzystanie z puli wątków systemu operacyjnego.
ThreadPool.QueueUserWorkItem(delegate { 
	// Tutaj czynności nie wymagające ingerencji w GUI.

	App.Current.Dispatcher.BeginInvoke(new Action(() => {
		// Tutaj aktualizacja GUI w wątku.
	}));
});
0

W sumie to chodziło mi tylko o to aby przy wysyłaniu requestów forma się nie zacinała bo akurat requestów leci około 4 tysięcy, zajmuje to z 10 min a przez ten czas forma jest zawieszona :/. Sam doszedłem do czegoś takiego, co prawda forma jest odcięta, normalnie w richTextBoxie moge pisać a requesty normalnie się wysyłają tylko problem z odświeżaniem labela.

Tutaj jest kod tworzenia nowego wątku:

                Thread threadMatch = new Thread(() =>
                {
                    Match(countCanta);
                });

                threadMatch.Start();

A początek metody Match wygląda tak:

public void Match(int size)
        {
            for (int a = 1; a < size; a++)
            {
                getA = a;
                label4.Text = getA.ToString();
                ...

Jeżeli przyjdzie czas na nadpisanie label4 to występuje taki błąd:
Cross-thread operation not valid: Control 'label4' accessed from a thread other than the thread it was created on.

0

Wszystko masz napisane w komunikacie. Integracja z GUI nie może zachodzić z poziomu osobnego wątki, tak jak chcesz to zrobić. Żeby zadziałało trzeba użyć Dispatcher'a, o którym pisałem wyżej. Dlatego Ci nie działa.

Ty próbujesz aktualizować GUI z wątku, w którym GUI nie ma i dlatego masz problem. Nawiasem mówiąc powinien Ci się wywalić wyjątek. Jeżeli tak nie jest to w ogóle coś źle robisz. EDIT: Fakt, wywalił Ci się wyjątek. Przeca jest komunikat :)

0
Krzywy Krawiec napisał(a):
public void abc(int size)
{
    for(int a = 0; a < size; a++)
    {
     //request
    }
}

przecież miało być co sekundę a tu się okazuje że wysyłasz wszystko na raz?

plątasz się w zeznaniach.

0
Azarien napisał(a):
Krzywy Krawiec napisał(a):
public void abc(int size)
{
    for(int a = 0; a < size; a++)
    {
     //request
    }
}

przecież miało być co sekundę a tu się okazuje że wysyłasz wszystko na raz?

plątasz się w zeznaniach.

Nie bierz tego dosłownie, chciałem przez to powiedzieć, że requesty lecą jeden za drugim i forma się zacina.

0

Nie bierz tego dosłownie, chciałem przez to powiedzieć, że requesty lecą jeden za drugim i forma się zacina.

No ale jak nie pokazujesz kodu prawdziwego, tylko jakieś //request, to jak mamy ci pomóc?

Co wysyła te "requesty"? Dlaczego one się generują - czy to jakiś timer jest, czy aktywność sieciowa...

InvokeRequired i Invoke rozwiązuje problem z dostępem do kontrolek z innego wątka.
Ale jeżeli u ciebie się forma zawiesza, to znaczy że główny wątek jest zajęty. Nie można tak sobie zrobić długotrwałej pętli w głównym wątku programu i jednocześnie mieć responsywnego GUI, bo kiedy ma się wykonać kod odpowiedzialny za GUI, skoro jest w tym samym wątku?
Pewnym półśrodkiem jest Application.DoEvents(), ale raczej trzeba kod przerobić tak, by DoEvents nie było potrzebne.
Być może najlepszym rozwiązaniem w twoim przypadku w ogóle nie są wątki, tylko async/await.

Ale kodu nie chcesz pokazać, tylko piszesz że "requesty lecą".
No to jak lecą to lecą...

0

Ale czy nie najlepiej zrobić to po prostu na zwykłym Task'u ? Po co się bawić w takiej sytuacji w BeginInvoke ?
Pozdr.
Astrocyt

0
Astrocyt napisał(a):

Ale czy nie najlepiej zrobić to po prostu na zwykłym Task'u ? Po co się bawić w takiej sytuacji w BeginInvoke ?
Pozdr.
Astrocyt

Invoke jest do tego, żeby zaktualizować kontrolkę z innego wątku.

0

A BackgroundWorker ci nie wystarczy? Wszystko zrobi za ciebie, tylko podłączyć się pod odpowiednie zdarzenia

0

W zupełności by wystarczył ale dobrze wiedzieć jak to działa pod spodem :)

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