ПРИНУДИТЕЛЬНОЕ закрытие «изгоев» потоков, если abort () не работает

#c# #multithreading #sockets #abort #forceclose

#c# #многопоточность #сокеты #прервать #принудительное закрытие

Вопрос:

Как следует из названия. Да, я знаю, что это ужасно использовать .abort(), но выслушайте меня

Я использую 2 потока: основной поток (моего приложения) и поток прослушивания сокета (знакомый звук кому-нибудь?) Вместо использования асинхронного.Вызовы AcceptAsync() (tbh, основная причина в том, что я не слишком много в них разбирался), у меня поток просто зависает на сокете.Accept(); Конечно, когда я вызываю thread .Abort(), поток не закрывается, потому что он все еще ожидает соединения, как только он пройдет Accept(), он будет прерван просто отлично.

Код:

     void listenserver()
    {
        while (run)
        {
            fConsole.WriteLine("Waiting for connections..");
            connectedsock = mainsock.Accept();
            connected = true;
            fConsole.WriteLine("Got connection from: "   connectedsock.RemoteEndPoint);
  


и в другом месте:

     private void button_start_Click(object sender, EventArgs e)
    {
        if (!run)
        { //code ommitted.
        }
      else
        {
            run = false;
            listenthread.Join(3000);
            if (listenthread.IsAlive)
            {
                fConsole.WriteLine("Force-closing rogue listen thread");
                listenthread.Abort();
            }
            button_start.Text = "Start";
            groupBox_settings.Enabled = true;
        }
  

есть ли какой-либо способ гарантировать, что поток завершится, а не запихивать все это в отдельное приложение, а затем завершать это?
Обратите внимание, что у меня есть поток.Для IsBackground установлено значение true (как предложено в других темах форума), однако это не имеет никакого значения.

Комментарии:

1. Если вы знаете это BeginAccept и EndAccept решите свои проблемы, почему вы продолжаете просить решение, которое не использует эти методы?

2. Потому что я хочу, чтобы одновременно было открыто только 1 соединение. и я знаю, что работа с async значительно расширит мой код, поэтому я подумал, что сделаю это как можно проще и сделаю это так. Думаю, это невозможно, тогда я просто использую acceptasync.

Ответ №1:

Поскольку вы уже используете поток, вы можете просто использовать BeginAccept . Асинхронный код не должен усложнять ваш код, поскольку вы можете использовать лямбды, подобные этому:

 var socket = new Socket(...);

socket.BeginAccept(result =>
{
    if (this.abort)
    {
        // We should probably use a signal, but either way, this is where we abort.
        return;
    }

    socket.EndAccept(result);
    // Do your sockety stuff
}, null);
  

Даже с отдельным определением метода для AsyncCallback , код не является сложным.

Выполняя асинхронный ввод-вывод, вы также намного эффективнее расходуете процессорное время, поскольку между вызовом BeginAccept и EndAccept поток может быть повторно использован для другой обработки. Поскольку вы не используете его ни для чего целенаправленного во время ожидания соединения, задержка потока довольно бессмысленна и неэффективна.

Комментарии:

1. Кажется разумным, но вы все равно должны поддерживать цикл потока, поскольку в противном случае программа завершит работу (поскольку в данном случае это консольный проект). Или BeginAccept() тоже блокирует поток? не будучи прерываемым, то есть .. — В любом случае, я отмечу это как хороший ответ, кроме того, я уже нашел способ уничтожить сокет, он выдаст прерываемое исключение, если вы закроете сокет в другом потоке, если вы справитесь с этим, вы сможете изящно закрыть поток.

2. Вам придется поддерживать поток GUI, да. BeginAccept немедленно вернется.