Problem z serwerem c#

0

Witam,
mam problem ze swoim serwerem, napisany jest w C#, problem polega na tym (podaje informacje od użytkowników) że:

  1. zawiesza się serwer (aplikacja) Framework 4 Client
  2. zawiesza się windows home (niestety to jest "serwer")
  3. aplikacja bądź windows home, generują lagi wysyłając z opóźnieniem informacje na port COM
    Cytując wyrwane części kodu, mniej więcej obrazujące zasadę działania serwera to wygląda to tak:
 // Tworzę TcpListener na porcie 6645
this.tcpListener = new TcpListener(IPAddress.Any, 6645);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();

 // do stworzonego powyżej wątku przekazuje tcpListener i w petli while(true) oczekuje i pobieram przychodzące połączenia:
  TcpClient client = this.tcpListener.AcceptTcpClient();

 // po odebraniu połączenia przekazuje client do następnego wątku na którym odbywa się wymiana danych między clientem i moim serwerem tj:
  ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClientComm), client);

 // nastepnie odbieram dane od polaczonego klienta
tcpClient = (TcpClient)client;
NetworkStream clientStream;
try
{
clientStream = tcpClient.GetStream();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
tcpClient.Close();
return;
}

byte[] message = new byte[4096];
int bytesRead;

bytesRead = 0;

// Odbieram dane
try {
bytesRead = clientStream.Read(message, 0, 4096);
}
catch {
// Jesli klient sie rozlaczyl i nie wyslal danych funkcja jest przerywana
return;
}

if (bytesRead == 0) {
return;
}
clientStream.Flush();

 // --- nastepnie obrabiam odebrane dane i dodaje je do kolejki ,Queue,
KolejkaCOM.Enqueue(text);
tcpClient.Close();
clientStream.Close();

 // dane z kolejki sa w osobnym Thread - watku wysylane co jakis czas na port COM, sa rowniez sciagane z kolejki zeby dane sie tam nie gromadzily tj:
  SerialPort port = new SerialPort(PortName, 9600, Parity.None, 8, StopBits.One);
text = (byte[])KolejkaCOM.Dequeue();
  port.Write(text, 0, text.Length);

W zasadzie to jest cała najważniejsza część programu i pytanie jest takie czy może coś źle zaprogramowałem i to jest powodem takich zawieszeń bądź opóźnień?
Dodam że serwer może przyjmować około 8 - 20 połączeń na minute (jednak może się zdażyć że 4-12 połączeń w danej sekundzie poprzez nakładanie się połączeń z losowości "wciskania przycisków" na pilotach przez użytkowników), dziennie około 2000, chociaż są to dane nie pewne.
Czy mógłbyś ktoś mi pomóc?
pozdrawiam

edit:

  1. dodam że program kompiluje przy pomocy VS2010 Express (aczkolwiek przy pomocy VS2010 ultimate sprawa wygląda tak samo)
  2. program nie zawiesza się od razu jest to że tak powiem losowe, czasem po 5minutach czasem po dwóch godzinach
0

klasa SerialPort implementuje interfejs IDisposable? skorzystaj z using. nie implementuje? jest tam metoda Close albo coś w tym rodzaju?

0

Witam,
klasa SerialPort implementuje IDisposable, rozumiem że radzisz skorzystać z using() a następnie korzystać z Dispose()?
Tylko jeśli dobrze zrozumiałem, ta funkcja czyści pamięć zarządzaną, jeśli czyści to co podawałem wcześniej na port COM (o ile jest to trzymane w pamięci) to na pewno ta funkcja się nada tylko czy czasem ona nie czyści uchwytu do portu USB który zapamiętany jest w zmiennej 'port' na której stworzyłem SerialPort?
Jest również metoda Close(), jednak dopóki serwer działa połączenie na porcie COM oraz połączenie z siecią LAN musi być aktywne,
gdyż serwer po otrzymaniu informacji (pakietu) z sieci LAN od urządzeń zewnętrznych od razu powinien wysłać wybraną paczkę do sieci logicznej po wspomnianym porcie COM.

  • port COM czyli virtualny port, a tak naprawdę port USB do którego podłączony jest Emulator portu COM *

edit:
użytkownicy dodali jeszcze taką sytuację że serwer potrafił się pozornie zawiesić (czyli pojawia się okno informujące o wystąpieniu błędu), jednak program dalej działał, to czwarta sytuacja, dopisuję może to komuś coś podpowie

0

w kodzie, który podałeś, nie było nigdzie wywołania Close() ani Dispose(), stąd moja sugestia. jeśli ręcznie niszczysz obiekt port, to spoko. using robi to, co Dispose(), Dispose() robi to, co ktoś zaprogramował. sprawdź co, to się dowiesz...
z kodu wynika również, że tworzysz obiekt port jako zmienną lokalną - może lepiej będzie trzymać go jako pole obiektu, na którym działa wątek?
niewykluczone, że błąd jest daleko poza Twoim kodem - skoro czasem zatrzymuje się cały system (!) to obstawiałbym błąd w sterowniku, chociaż wtedy powinieneś zobaczyć BSOD. powiem Ci, że jeszcze nie widziałem, żeby system z linii NT zawiesił się w sposób inny, niż BSOD.

0

Tak, faktycznie wyrwałem kod i nie skopiowałem metody close() oczywiście z niej korzystam, sprawa jednak jest taka że serwer - czyli maszyna (z osadzonym windows 7 home) przeważnie pracuje od rana do wieczora i tak zastanawiam się czy "otwarty" port COM (virtualny USB - konweter USB -> COM) będzie odpowiadał przez cały dzień, na ogól odpowiada jednak nie zawsze. Wszystko ustawiłem w tryby "bądź uruchomiony non stop", porty USB, system, dyski tak że nie powinno się nic usypiać/hibernować. Czy jest cień szansy że jednak powinienem co jakiś czas zamykać SerialPort, a następnie znów stworzyć 'nowe połączenie'?
Dodam że najciekawsze błędy jak wyżej pisałem to pozorne zawieszenia, wyskakuje komunikat "program przestał odpowiadać/działać", jednak program działa w 100% tak jak powinien.

0

"błędem" "program przestał odpowiadać" zbytnio się nie przejmuj, wynika on z tego, że program przez dłuższy czas nie obsługuje kolejki zdarzeń. świadczy to o tym, że główny wątek programu nad czymś pracuje (być może w wyniku błędu wpadł gdzieś w nieskończoną pętlę). owszem, wypadałoby poprawić kod tak, żeby pracą zajmowały się osobne wątki, a główny służył tylko do obsługi gui, ale nie jest to szczególnie istotne na tym etapie; z drugiej strony, skoro operacje zajmujące czas już masz w osobnym wątku, to główny wątek nie powinien "stawać", a jeśli tak robi, to pachnie błędem w Twoim kodzie.
IMHO port powinien odpowiadać cały czas, ale po ostatnich przejściach z msmq i expression encoderem wiem już, że w tych samych warunkach oprogramowanie nie zawsze działa tak samo (!) i mogą się znienacka pojawiać praktycznie losowe błędy. jak sobie z tym radzić? obok wątku komunikacji (K) żyje drugi wątek - watchdog (W). wątek K co pewien czas "resetuje" watchdoga, np. co kilka sekund ustawia jakieś swoje publiczne pole (T) na aktualną datę/godzinę. z kolei wątek W sprawdza, czy pole T nie jest starsze niż ustalony jakiś czas. jeśli jest starsze, to W pauzuje K, usiłuje zamknąć serialport (zakładając, że ta operacja nie zawiesi również W), zabija wątek K i tworzy jego nową instancję. z tego powodu kolejka danych powinna znaleźć się poza obiektem wątku K, ale to już szczegóły implementacyjne.

0

Już wszystko ogarnięte (prawie ale działa jak trzeba)
pozdrawiam

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