Вызовы Asynch против многопоточности - PullRequest
2 голосов
/ 01 июня 2011

У меня есть служба Windows в VB.NET, которая последовательно обращается к нескольким долго выполняющимся процессам (обычные подпрограммы, а не веб-svc, удаленное взаимодействие или что-нибудь необычное). Я настаиваю на том, чтобы пытаться реализовать многопоточность только потому, что мы никогда не делали этого раньше, и это очень важный код. У меня была мысль вызвать асинхронные процедуры вместо этого. Я знаком с этим и использую его как часть некоторых веб-сервисов. Я что-то пропустил? Похоже, что асинхронные вызовы - это способ избежать проблем с многопоточностью.

Ответы [ 3 ]

1 голос
/ 01 июня 2011

Похоже, что асинхронные вызовы - это способ избежать проблем с многопоточностью.

Не обязательно. Javascript (и серверные варианты Javascript, такие как Node.js) работают в одном потоке, но используют много асинхронности, так что не тратится много времени на ожидание завершения длительной операции. Это способ оптимизации одного потока и очень мощный способ программирования, если вы правильно настроены.

Если вы знакомы с асинхронным программированием, сделайте это! Нет необходимости вводить много потоков только потому, что задача МОЖЕТ быть распараллелена.

Однако, если задачи связаны с процессором, то один поток захлебнется, и асинхронность не поможет вам по понятным причинам. Если задача IO, то асинхронность - это, вероятно, верный путь.

Edit:

Извините, я не понял. Под связыванием ЦП я имел в виду, что если в конкретной операции используется много ЦП, поток будет постоянно использоваться и не будет доступен для других задач.

Например:

// task
long sum = 0;
for (int i = 0; i < 1000000; i++)
    for (int j = 1000000; j > 0; j--)
         sum = i + j;

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

// task
List<string> urls = GetListOfUrls();
List<string> html = new List<string>();
foreach (var url in urls) 
{
    GetUrlAsync(url, callback: (data) => html.Add(data) );
}

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

Итак, если ваши задачи будут тратить много времени на ожидание внешнего процесса, используйте асинхронность. Если задачи будут записывать на процессор, используйте несколько потоков.

1 голос
/ 02 июня 2011

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

В любом случае, у вас все еще есть проблемы с параллелизмом.

Вы можете использовать асинхронные вызовы для длительных задач. На самом деле класс Task имеет конструктор, который позволяет указывать параметры создания , включая TaskCreationOptions.LongRunning.

Управлять своими собственными потоками с помощью класса Thread немного сложнее, чем с помощью чего-то вроде Task или ThreadPool.QueueUserWorkItem, но это также дает вам немного больший контроль. В любом случае вам придется иметь дело с проблемами параллелизма, такими как состояние гонки и поточно-ориентированные структуры данных (если несколько потоков изменяют структуру данных). Я бы не назвал асинхронные вызовы «многопоточностью бедняков». Различия не так велики. Это просто два разных способа сделать одно и то же.

1 голос
/ 01 июня 2011

Асинхронные вызовы обычно лучше, чем обычная многопоточность, потому что они используют поток портов ввода-вывода, который более эффективен с точки зрения использования процессора.

...