Wątki w C# - parę pytań


(northwest) #1

Witam serdecznie,

Mam następujący kod:

class Program

{

static StreamReader streader = null;

static StreamWriter write = null;

static TcpClient serwer = null;

static Byte[] bufor = null;

static NetworkStream netstream=null;

private static void reader()

{

while (true)

{

int lData = netstream.Read(bufor, 0, serwer.Client.ReceiveBufferSize);

String myString = Encoding.ASCII.GetString(bufor);

myString = myString.Substring(0, lData);

Console.WriteLine(myString);

}

}

private static void writer()

{

while (true)

{

String myString = Console.ReadLine() + "\n";

netstream.Write(Encoding.ASCII.GetBytes(myString.ToCharArray()), 0, myString.Length);

}

}

static void Main(string[] args)

{

try

{

String host = "192.168.1.149";

serwer = new TcpClient(host, 8081);

if (serwer.Client.Connected)

{

Console.WriteLine("Połączono z serwerem:" + host);

netstream = serwer.GetStream();

bufor = new byte[serwer.Client.ReceiveBufferSize];

new Thread(new ThreadStart(writer)).Start();

new Thread(new ThreadStart(reader)).Start();

String myString = "nnnnnnnnnnnnnnnnnn";

netstream.Write(Encoding.ASCII.GetBytes(myString.ToCharArray()), 0, myString.Length);

}

else

Console.WriteLine("Nie połączono ze zdalnym hostem");

}

catch (SocketException se)

{

Console.WriteLine("Błąd : " + se.Message);

}

}

}

chciałbym do niego dorobić 2 rzeczy:

  • po wpisaniu słowa "EXIT" chciałbym żeby wątek się zakończył

  • chciałbym żeby do tekstu "Połączono z serwerem" doszła informacja o IP komputera na którym została uruchomiona aplikacja

Wiecie może jak to zrobić??

Ogólnie po zerwaniu połączenia wątek się automatycznie zakańcza, ale ja chciałbym programowo zamykać/otwierać (otwieranie mam) wątki... Wie ktoś może jak to zrobić??

Z góry dzięki za pomoc,

Pozdrawiam Northwest


(Gryph) #2

Czesc,

Thread.Abort() - ta funkcja konczy watek. Utworz sobie w kodzie obiekty typu Thread, np tak:

Thread watek = new Thread(new ThreadStart(nazwa_funkcji));

...Wtedy mozesz startowac, wstrzymywac i zatrzymywac watek. Mozesz takze badac stan watku.

Np tak:

private String podaj_ip()

{

    IPHostEntry he= Dns.GetHostEntry(Dns.GetHostName());

    String moje_ip = “”;


    foreach (IPAddress ip in he.AddressList)

    {

        if (ip.AddressFamily.ToString() == “InterNetwork”)

        {

             moje_ip = ip.ToString();

        }

   }


   return moje_ip;

}

Pozdrawiam


(northwest) #3

qurcze funkcja od ip nie działa:

Error 1 'Socket1.Program.podaj_ip()': not all code paths return a value Program.cs 31 24 ConsoleApplication1

obsługa wątku działa super:)

Thread watek = new Thread(new ThreadStart(reader));

watek.Start();

watek.Abort();

a jak wstrzymać działanie wątku np. na 12 sekund??

Idzie jakoś sprawdzić co się dzieje w danym momencie w danym wątku (z poziomu obsługi wątku)??


(Gryph) #4

Wstrzymanie watku:

Thread.Sleep(12000); //czas podajesz w milisekundach.

Funkcja od IP:

Kod przekleiles dobrze? Podaj moze funkcje, gdzie to wywolujesz...

Co do badania watku - mozesz sprawdzic stan (chyba sie to nazywa ThreadState) - ale co rozumiesz przez "co sie dzieje" ?


(northwest) #5

ja po prostu wkleiłem Twoją funkcję - bez wywoływania jeszcze. Visual Studio od razu zwraca błąd w private String podaj_ip():

Error 1 'Socket1.Program.podaj_ip()': not all code paths return a value Program.cs 31 24 ConsoleApplication1

czyli watek.ThreadState()??

ogólnie chciałem się dowiedzieć o stanie wątku - do tego jest ten ThreatState??

da się sprawdzić ile pamięci ram zajmuje wywołany wątek (też programowo)??


(Gryph) #6

U mnie dziala ok. Dziwne.... ;0

Co do watkow - ThreadState to typ wyliczeniowy i pokazuje Ci stan watku.

Zeby zobaczyc ile zajmuje w RAMie - ja bym skorzystal z Process.GetCurrentProcess() - zwraca Ci obecny proces (czyli najczesciej aplikacje). Tu mozesz sprawdzic wszystko - alokowanie RAMu, strony, obciazenie procka. Itp. itd....

Zeby dojsc do watku - w klasie Process masz skladowa Threads - przejrzyj.

Pozdrowienia


(northwest) #7

Mam taki kod:

namespace Socket1

{

    class Program

    {

        static StreamReader streader = null;

        static StreamWriter write = null;

        static TcpClient serwer = null;

        static Byte[] bufor = null;

        static NetworkStream netstream=null;

        private static void reader()

        {

            while (true)

            {

               int lData = netstream.Read(bufor, 0, serwer.Client.ReceiveBufferSize);

               String myString = Encoding.ASCII.GetString(bufor);

               myString = myString.Substring(0, lData);

               Console.WriteLine(myString);

            }

        }

        private String podaj_ip()

        {

            IPHostEntry he = Dns.GetHostEntry(Dns.GetHostName());

            String moje_ip = "";


            foreach (IPAddress ip in he.AddressList)

            {

                if (ip.AddressFamily.ToString() == "InterNetwork")

                {

                    moje_ip = ip.ToString();

                }

            }

        }

        private static void writer()

        {

            while (true)

            {

                String myString = Console.ReadLine() + "\n";

                netstream.Write(Encoding.ASCII.GetBytes(myString.ToCharArray()), 0, myString.Length);

            }

        }       

        static void Main(string[] args)

        {

            try

            {

                    String host = "192.168.1.149";

                    serwer = new TcpClient(host, 8081);

                    if (serwer.Client.Connected)

                    {

                       // String a = podaj_ip();

                        Console.WriteLine("Połączono z serwerem:" + host);

                        netstream = serwer.GetStream();

                        bufor = new byte[serwer.Client.ReceiveBufferSize];

                        new Thread(new ThreadStart(writer)).Start();

                        Thread bla = new Thread(new ThreadStart(reader));

                        Process mem = Process.GetCurrentProcess();

                        String myString = "nnnnnnnnnnnnnnnnnn";

                        netstream.Write(Encoding.ASCII.GetBytes(myString.ToCharArray()), 0, myString.Length);

                    }

                    else

                        Console.WriteLine("Nie połączono ze zdalnym hostem");

                }

            catch (SocketException se)

            {

                Console.WriteLine("Błąd : " + se.Message);

            }

        }

    }

}

i ta Twoja funkcja nie działa :frowning:

Sprawdzanie pamięci robi się jakoś tak:

Process mem = Process.GetCurrentProcess();

Console.Write(mem.ToString()); ??

jak się wywołuje tego ThreadState do konsoli??

dzięki WIELKIE za pomoc:)


(Gryph) #8

No i wszystko jasne - nie przekleiles jednej linii - przedostatniej ("return moje_ip"). :wink: :wink: :wink:

Inna rzecz:

Process mem = Process.GetCurrentProcess();

Console.Write(mem.ToString());

Powyzszy kod nic Ci nie da poza prawdopodobnie nazwa klasy. Musisz wywolac odpowiednia funkcje lub pole. Opis znajdziesz w MSDN.

Wybacz - ostatniego pytania nie rozumiem.

Pozdro


(northwest) #9

fakt, ale gafa... przegapiłem kawałek kodu :x

chciałbym wyświetlić działanie ThreadState w konsoli - wiesz może jak to zrobić??:slight_smile:


(Gryph) #10

Najprosciej to zrobic serie klauzul "if" i odpowiednio formatowac string wyjsciowy.

Jak pisałem powyżej - ThreadState to typ wyliczeniowy, czyli posiada okreslona liste wartosci.


(northwest) #11

oki, a jak wyświetlić ten nie sformatowany ciąg wartości??:wink:


(Gryph) #12

Dziala to:

Thread bla = new Thread(new ThreadStart(reader));

Console.WriteLine("ThreadState: {0}",watek.ThreadState);

???

Sprawdz, nie mam teraz mozliwosci.


(northwest) #13

działa, dzięki!!:slight_smile: