2015-05-03 4 views
3

Я очень запутался здесь в многопоточности :( Я читаю о ключевых словах C# Async/Await. Часто читаю, что с помощью этой функции async код запускается " без блокировки ». Люди помещают примеры кода в две категории« IO-Bound »и« CPU-bound »- и что я не должен использовать поток, когда я выполняю связанные с io вещи, потому что этот поток будет просто ждать ..Threads, Task, async/await, Threadpool

Я не понимаю ... Если я не хочу, чтобы пользователь должен был ждать операции, я должен выполнить эту операцию в другом потоке, правильно?

Если я использую Threadpool, экземпляр «Thread» «класс, делегат.BeginInvoke или TPL - каждый синхронное выполнение выполняется в другом потоке. (С или без обратного вызова)

+2

Темы - один из способов достижения асинхронности, но асинхронность не требует использования потоков.См. Статью Стивена Клири, [No No Thread] (http://blog.stephencleary.com/2013/11/there-is-no-thread.html). –

+0

MS действительно выполнил довольно приличную работу по документированию этого. Не уверен, прочитали ли вы руководство по асинхронному программированию ... но вы должны: https://msdn.microsoft.com/en-us/library/hh191443.aspx –

+0

Кроме того, для очень хорошего введения в потоки в C# вы может захотеть прочитать это http://www.albahari.com/threading/ – Alex

ответ

5

Что вам не хватает, так это то, что не каждая асинхронная операция выполняется в другом потоке. Ожидание операции ввода-вывода или вызова веб-службы не требует создания потока. В Windows это делается с использованием OS I/O Completion Ports.

Что происходит, когда вы вызываете что-то вроде Stream.ReadAsync, это то, что ОС выдаст команду чтения на диск, а затем вернется к вызывающему. Как только диск завершит чтение, вы узнаете о ядре ОС, которое затем вызовет обращение к вашим процессам. Поэтому нет необходимости создавать новый поток threadpool, который будет просто сидеть и блокироваться.

+0

Интересно - я всю жизнь работаю с Windows (так оно себя чувствует), и я не знал о завершении ввода-вывода ввода-вывода. Немного о Поиске Google нашел это: http://stackoverflow.com/questions/5283032/io-completion-ports-advantages-and-disadvantages – RenniePet

+0

Итак .. с этими портами ввода-вывода ввода-вывода .. Могу ли я написать свое собственное использование метода те .. как MyClass.DoSomethingAsyncWithoutUsingThreads()? –

+0

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

2

Что означает это:

Предположим, вы запрашиваете некоторые данные из базы данных (на другом сервере) - вы будете посылать запрос и просто ждать ответа. Вместо того, чтобы иметь блок потока и ждать возврата, лучше зарегистрировать обратный вызов, который будет вызван, когда данные вернутся - это (более или менее) то, что делает асинхронный/ожидающий. Он освободит поток, чтобы делать другие вещи (верните его в пул), но как только ваши данные возвратятся асинхронно, он получит еще один поток и продолжит ваш код в точке , вы оставили (это действительно какая-то государственная машина который обрабатывает это).

Если ваши вычисления действительно интенсивно работают в ЦП (скажем, вы вычисляете простые числа), все по-другому - вы не ожидаете какого-либо внешнего ввода-вывода, вы делаете тяжелую работу над ЦП - здесь лучше использовать нить, чтобы ваш пользовательский интерфейс не блокировался.

1

Я не понимаю ... Если я не хочу, чтобы пользователь должен был ждать операции, я должен выполнить эту операцию в другом потоке, правильно?

Не совсем. Операция будет длиться долгое время. Когда у вас однопользовательское приложение, работа на длинных ресурсах в отдельном потоке позволяет пользовательскому интерфейсу оставаться отзывчивым. По крайней мере, это позволяет UI иметь что-то вроде кнопки «Отмена», которая может принимать пользовательский ввод и отменять обработку на другом потоке. Для некоторых однопользовательских приложений имеет смысл позволить пользователю продолжать делать другие вещи, в то время как длительная задача завершается (например, пусть они работают с одним файлом, когда другой файл загружается или загружается).

Для веб-приложений вы не хотите блокировать поток из пула потоков при длительном (ish) IO, например, при чтении из базы данных или вызове другой веб-службы. Это связано с тем, что в пуле потоков имеется ограниченное количество потоков, и если они все используются, веб-сервер не сможет принимать дополнительные HTTP-запросы.

Смежные вопросы