Wywoływanie zdarzeń z innego wątku

0

Powiedzmy że chcę stworzyć klasę która działa w innym wątku i chcę żeby ona pozwalała na obsługiwanie zdarzeń. Jak to zrobić żeby użytkownik klasy nie musiał robić Invoke przy każdym odwołaniu się do UI w wywoływanych zdarzeniach?

0

Ogolnie mowiac, zdarzenie 'jest odpalane' przez watek poboczny, wiec wszystkie podpiete do niego eventhandlery zostana wykonane przez wlasnie ten watek. Control.Invoke jest potrzebne, aby "przeniesc" sie z wykonywaniem "wskazanego kodu" do innego watku - teog ktory trzyma dana Control'kę. Jezeli pozwolisz aby po porstu sobie Twoj watek poboczny odpalil event, to nie ma bata - w eventhandlerach bedziesz musial testowac InvokeRequired i Invoke'owac jesli trzeba.

Jezeli nie masz silnego uzasadnienia dla wlasnorecznego tworzenia i pilnowania watkow, uzyj BackgroundWorker - on ma tak eventy progressreport/completed przygotowane, ze zostana one odpalone w watku ktory stworzyl tego BGW a nie w watku ktory BGW uzywa jako roboczy - i w handlerach podpietych do jego Completed spokojnie mozesz uzywac kontrolek GUI bez CrossThreadException

0

dziękuję bardzo za odpowiedź
właściwie to tworzę powiedzmy tunel i miałem zamiar w osobnym wątku korzystając z socketów nasłuchiwać na połączenie - dlatego raczej muszę skorzystać z osobnego, zarządzanego przeze mnie wątku (chyba że jest jakiś inny pomysł), a w głównej aplikacji miałem zamiar obsługiwać tylko zdarzenia stworzone przeze mnie typu onconnect, ondisconnect i parę podobnych

0

zle to robisz.
blokowanie calego watku czekajac na zakonczenie IO to marnowanie zasobow.

stworz 1 watek, i w nim odpowiednio obsluguj eventy. wszsytkie operacje rob z uzyciem struktury OVERLAPPED, tam jest event ktory ma kluczowa role w synchronizacji.

jest to trudniejsze, ale poprawne. aha, i nie uzywaj funkcji z callbackami typu ReadFileEx - nie mozna im przekazac wlasnych danych, wiec sa one bez sensu.

0
socket11 napisał(a)

zle to robisz.
blokowanie calego watku czekajac na zakonczenie IO to marnowanie zasobow.

stworz 1 watek, i w nim odpowiednio obsluguj eventy. wszsytkie operacje rob z uzyciem struktury OVERLAPPED, tam jest event ktory ma kluczowa role w synchronizacji.

jest to trudniejsze, ale poprawne. aha, i nie uzywaj funkcji z callbackami typu ReadFileEx - nie mozna im przekazac wlasnych danych, wiec sa one bez sensu.

kompletnie mnie zgubiłeś.
mógłbyś trochę rozwinąć temat? o jaki event chodzi i może jakiś link do przykładowego kodu?
o ile się nie mylę to to wszystko ma powiązanie z winapi, nie da się tego zrealizować poprawnie w ".NETowski" sposób?

0

właściwie to w "niewłaściwy sposób" zrealizowałbym już całą aplikację dwa dni temu.
no ale chciałbym się czegoś przy okazji nauczyć :)

1

Zastanowiłem się nad twoim pomysłem, i właściwie nie jest aż taki zły, tylko że po co tak kombinujesz :] Jeśli nie tworzysz serwera, to nie ma sensu zamulać komputera dwoma wątkami (a jeśli masz jednordzeniowca to nie ma sensu w ogóle używać wątków). Prościej by było obiektowo ;). Ale jeśli tworzysz serwer czy inną aplikację która ma z założenia zajmować całe CPU, w dodatku wymagającą obliczeniowo, to ok, zostaw jak jest :)

0

Poczytaj o SynchronizationContext. Tutaj jest ciekawy artykuł.

0
MSM napisał(a)

Zastanowiłem się nad twoim pomysłem, i właściwie nie jest aż taki zły, tylko że po co tak kombinujesz :] Jeśli nie tworzysz serwera, to nie ma sensu zamulać komputera dwoma wątkami (a jeśli masz jednordzeniowca to nie ma sensu w ogóle używać wątków). Prościej by było obiektowo ;). Ale jeśli tworzysz serwer czy inną aplikację która ma z założenia zajmować całe CPU, w dodatku wymagającą obliczeniowo, to ok, zostaw jak jest :)

właściwie z tego co wyczytałem to nie ma opcji żeby nie tworzyć innego wątku
jeśli skorzystamy w jednym wątku z nieblokujących metod asynchronicznych to i tak wątek zostanie utworzony tyle że na poziomie systemu, tak więc wychodzi na to samo tylko że mamy nad nim mniejszą kontrolę (tak wyczytałem)

dzięki bardzo, Mendoza to wygląda dokładnie na to czego szukałem

0

ok, niech mi ktoś tylko pomoże uporządkować kod
nie chciałem za każdym razem pisać czegoś w stylu:

asyncOperation.Post(new SendOrPostCallback(delegate(object state)
	{
		ReadData(this, new DataEventArgs(client, data);
	}
), null); // wywołanie zdarzenia ReadData przekazując "client" i "data"

asyncOperation.Post(new SendOrPostCallback(delegate(object state)
	{
		ClientConnected(this, new ClientConnectionEventArgs(client, id);
	}
), null); // wywołanie zdarzenia ClientConnected przekazując "client" i "id"

więc początkowo przerobiłem to na:

RaiseReadData(client, data);
RaiseClientConnected(client, id);

void RaiseReadData(Socket client, ServerClientData data)
{
	asyncOperation.Post(new SendOrPostCallback(delegate(object state)
	{
		ReadData(this, new DataEventArgs(client, data));
	}
	), null);
}

void RaiseClientConnected(Socket client, Int32 id)
{
	asyncOperation.Post(new SendOrPostCallback(delegate(object state)
	{
		ReadData(this, new ClientConnectionEventArgs(client, id));
	}
	), null);
}

ale to było jeszcze gorsze i każde dodatkowe zdarzenie to problem więc zrobiłem z tego:

RaiseEvent<DataEventArgs>(new EventHandler<DataEventArgs>(ReadData), new DataEventArgs(client, data));
RaiseEvent<ClientConnectionEventArgs(new EventHandler<ClientConnectionEventArgs>(ClientConnected), new ClientConnectionEventArgs(client, id));

void RaiseEvent<T>(EventHandler<T> _event, T args) where T: EventArgs
{
	asyncOperation.Post(new SendOrPostCallback(delegate(object state)
		{
			_event(this, args);
		}
	), null);
}

i to choć najkrótsze to wygląda kretyńsko i w dodatku skomplikowanie chociaż takie nie jest :|

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