Wątki - Threads C#

0

Witam, jak w temacie:
otwieram kilka wątków i chcę z pozycji konsoli zamknąć. Chcę je zamykać po ID, ale nie ID bieżącego wątku. Wyczytałem także, żeby lepiej nie używać funkcji .Abort.
Thread 10
Thread 11
Thread 12

z pozycji konsoli chciałbym np zamknąć 11, a aktualnie używanym jest 12.

0

Wątek 12 odpalasz w 11?

0

Może powiedz co właściwie robisz, bo jestem pewien, że da się to zrobić lepiej.

0
Rev napisał(a):

Może powiedz co właściwie robisz, bo jestem pewien, że da się to zrobić lepiej.

robię przykładowy serwer tcp. Aplikacja konsolowa. Najważniejsze jego zadania to:

  • rozłączenie klienta z pozycji konsoli - na jakąś komendę
  • zamknięcie wątku roboczego komunikatu od klienta z (bez Abort) konsoli, ale niekoniecznie ostatnio uruchomionego

Wklejam kod:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace serverekTCP
{
    class Server
    {
        private TcpListener tcpListener;
        private Thread listenThread;

        public Server(int port)
        {
            this.tcpListener = new TcpListener(IPAddress.Any, port);
            this.listenThread = new Thread(new ThreadStart(ListenForClients));
            this.listenThread.Start();
            LogMessage("Serwer jest uruchomiony !");
            LogMessage("Nasłuchuje na porcie: " + port);
            LogMessage("Oczekuję na połączenie klienta...");
        }

        private void ListenForClients()
        {
            this.tcpListener.Start();

            while (true)
            {
                try
                {
                    TcpClient client = this.tcpListener.AcceptTcpClient();
                    Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                    clientThread.Start(client);
                }
                catch(Exception exp)
                {
                    LogMessage(exp.ToString());
                }

            }
        }

        private void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            ASCIIEncoding encoder = new ASCIIEncoding();

            string clientInfo = tcpClient.Client.RemoteEndPoint.ToString();
            LogMessage(string.Format("Nawiązano połączenie z klientem {0}", clientInfo));
            try
            {
                using (var networkStream = tcpClient.GetStream())
                using (var reader = new StreamReader(networkStream))
                using (var writer = new StreamWriter(networkStream))
                {
                    writer.AutoFlush = true;
                    while (true)
                    {
                        var dataFromServer = reader.ReadLine();
                        if (string.IsNullOrEmpty(dataFromServer))
                        {
                            break;
                        }
                        LogMessage(dataFromServer);
                        writer.WriteLine("Dziękujemy za wiadomość:" + dataFromServer);
                        Thread closeConnThread = new Thread(new ThreadStart(CloseConnection));
                        closeConnThread.Start();
                    }
                }
            }
            catch (Exception exp)
            {
                LogMessage(exp.Message);
            }
            finally
            {
                LogMessage(string.Format("Zamknięto połączenie z klientem - {0}",
                            clientInfo));
                tcpClient.Close();
            }
        }

        //kod
        //private void CloseConnection()
        //{
        //    string close = Console.ReadLine();
        //    string zamknij = "close-" + Thread.CurrentContext.ContextID.ToString();
        //    if (close == zamknij)
        //        Console.WriteLine(zamknij);
        //    else
        //        Console.WriteLine("inny");
        //}
        //wiadomość
        private void LogMessage(string message)
        {
            System.Console.WriteLine("[{0}]: Thread-{1}- {2}", DateTime.Now, Thread.CurrentThread.ManagedThreadId, message);
        }

    }
}
 
0
Noodle napisał(a):

Wątek 12 odpalasz w 11?
nie, każdy to osobny wątek.
wątek 11 komunikaty od klienta 1
wątek 12 komunikaty od klienta 2...

0

Rozwiązaniem łopatologicznym było by stworzenie globalnej tablicy string-ów lub boolean-ów o wielkości dopuszczalnych jednoczesnych połączeń i przekazwywanie w parametrze do HandleClientComm(object client) dodatkowo Id do którego elementu tablicy dany wątek ma się odnosić i w odpowiednim momencie w kodzie HandleClientComm sprawdzać element tablicy, wyświetlić komunikat i bezpiecznie zamknąć połączenie. Problem że wszystkie wątki odwoływały by się do jednej tablicy co pewnie wywali exeption ale przy użyciu semaforów na pewno jakoś by się to dało z synchronizować. Kolejny problem że każdy wątek będzie oczekiwał na wszystkie inne, aż zwolnią dostęp do tej zmiennej i o ile to będzie parę połączeń to może i to będzie działać o tyle jeżeli to będzie 100 wątków to nie jestem pewien. I do tego oczywiście z poziomu twojego programu czyli wątku głównego chcąc zamknąć dany wątek odpowiedni do Id element tablicy ustawiasz na true lub wpisujesz jakiś komunikat. Teoretycznie powinno działać:)
Pozdrawiam

PS. Zaciekawił mnie temat i doszkoliłem się przy okazji trochę z wątków. Okazuje się że w tym przypadku obejdzie się bez semaforów locków itp. Polecam artykuł: Bezpieczny dostęp do danych. I przy okazji napisałem prosty kod dla sprawdzenia.

   
static private bool[] StopThread = new bool[10];

        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                StopThread[i] = false;  
                Thread T = new Thread(new ParameterizedThreadStart(DoWorkT));
                T.Start((object)i);
            }


            while (true)
            {
                LogMessage(string.Format("Wpisz nr wątku do zamknięcia: "));
                
               string nr = System.Console.ReadLine();

                StopThread[Convert.ToInt16(nr)] = true;
            }
        }

  static private void DoWorkT(object arg)
        {
            int T_id = (int)arg;

            LogMessage(string.Format("Wątek nr. {0} uruchomiony", T_id));

            while (true)
            {

                if (StopThread[T_id])
                {
                    LogMessage(string.Format("Wątek nr. {0} Zakończony", T_id));
                    Thread.CurrentThread.Abort();
                }

            }


        }

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