#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
немедленно вернется.