Этот вопрос касается не дизайнов и моделей, а использования. В основе этого вопроса лежит то, что происходит в отношении потоков и блокировки.Длинные блокирующие методы. Разница между блокировкой, спящим, началом/концом и Async
Этот пример применим к любому методу блокировки, который предназначен для непрерывного выполнения одного и того же действия. В этом случае это блокировка чтения или записи в сетевом потоке. Есть ли заметная разница за кулисами в отношении потоков и производительности между методами?
Мое предположение заключается в том, что каждый из приведенных ниже способов создает поток или использует объединенный поток. Затем блокирует этот поток до тех пор, пока не будут прочитаны данные. Сказав это и в этом контексте, есть ли какая-то заметная разница в отношении потоковой обработки, производительности и масштабируемости между методами?
В настоящее время я создаю серверное приложение. Это приложение будет иметь 1000 клиентов, создающих tcp-соединения. Эти соединения будут оставаться открытыми, часто отправляя и получая небольшие объемы данных. Я ищу использовать модель A, поскольку она проще всего реализовать и наиболее удобна в обслуживании. Будет ли в конечном итоге 1000 потоков независимо от того, какой шаблон выбран?
Обратите внимание, что эти методы предназначены только для того, чтобы дать представление о структуре, а не о том, что будет использоваться без правильных потоковых чтений, тайм-аутов и обработки исключений.
Метод A: Блокирование
Task.Factory.StartNew(ReadMessage,TaskCreationOptions.LongRunning);
private void ReadMessage()
{
while(true)
{
TcpClient.Read();
}
}
Метод B: Спящий
Task.Factory.StartNew(ReadMessage,TaskCreationOptions.LongRunning);
private void ReadMessage()
{
while(true)
{
if(TcpClient.DataAvailable)
TcpClient.Read();
else
Thread.Sleep(1);
}
}
Метод C: Рекурсивный Начало/Конец
private void ReadMessage()
{
stream.BeginRead(readCallBack)
}
private void readCallBack()
{
stream.EndRead();
stream.BeginRead(readCallBack)
}
Метод D: Асинхронный из BCL socket.ReceiveAsync ()
private void readCallBack()
{
while(true)
{
await socket.ReceiveAsync(eventArgs);
}
}
Метод E: метод Асинхронный с блокированием Read (Использует метод D для вызова, но пользовательский метод вместо использования встроенного в exstendion сокетов от BCL)
private async Task<byte[]> ReceiveAsync()
{
return await Task.Factory.StartNew(() => TcpClient.Read());
}
Благодарим вас за разъяснения. Это действительно помогло.Мой последний вопрос был бы, есть ли разница между методом D и новым методом E? Может ли метод E быть таким же результативным в том, что он не блокирует потоки и вместо этого использует IOCP? –
Блокирующий вызов ввода/вывода в методе «async» никогда не является хорошей идеей. Метод E блокирует вызывающий поток и не использует IOCP. Методы C и D используют IOCP и не блокируют вызывающий поток. –
Исправлен метод E по вашему предложению. Я полагаю, что ответ остается в том, что он заблокирует поток и не будет использовать IOCP –