В настоящее время я работаю над серверным приложением, которое должно управлять устройствами сбора данных по сети. Из-за этого нам нужно много параллельного программирования. Со временем я узнал, что существует три подхода к взаимодействию между объектами обработки (потоками / процессами / приложениями). К сожалению, все три подхода имеют свои недостатки .
A) Вы можете сделать синхронный запрос (синхронный вызов функции). В этом случае вызывающая сторона ожидает, пока функция не будет обработана и ответ не будет получен. Например:
const bool convertedSuccessfully = Sync_ConvertMovie(params);
Проблема в том, что вызывающий абонент бездействует. Иногда это просто не вариант. Например, если вызов был выполнен потоком пользовательского интерфейса, может показаться, что приложение заблокировано до получения ответа, что может занять много времени.
B) Вы можете сделать асинхронный запрос и дождаться обратного вызова . Код клиента может продолжаться с любыми необходимыми действиями.
Async_ConvertMovie(params, TheFunctionToCallWhenTheResponseArrives);
Это решение имеет большое неудобство, что функция обратного вызова обязательно выполняется в отдельном потоке. Проблема в том, что теперь трудно вернуть ответ вызывающей стороне. Например, вы нажали кнопку в диалоговом окне, которое вызывало службу асинхронно, но диалоговое окно было долго закрыто, когда поступил обратный вызов.
void TheFunctionToCallWhenTheResponseArrives()
{
//Difficulty 1: how to get to the dialog instance?
//Difficulty 2: how to guarantee in a thread-safe manner that
// the dialog instance is still valid?
}
Само по себе это не такая большая проблема. Однако, когда вы хотите сделать более одного из таких звонков, и все они зависят от ответа предыдущего, в моем опыте это становится неуправляемо сложным .
C) Последний вариант, который я вижу, - сделать асинхронный запрос и продолжать опрашивать до получения ответа. В промежутках между проверками «есть ответ, пришедший еще» вы можете сделать что-то полезное. Это лучшее из известных мне решений для решения случая, когда необходимо выполнить последовательность асинхронных вызовов функций. Это потому, что у него есть большое преимущество в том, что у вас все еще есть весь контекст вызывающей стороны, когда приходит ответ. Кроме того, логическая последовательность вызовов остается достаточно ясной. Например:
const CallHandle c1 = Sync_ConvertMovie(sourceFile, destFile);
while(!c1.ResponseHasArrived())
{
//... do something in the meanwhile
}
if (!c1.IsSuccessful())
return;
const CallHandle c2 = Sync_CopyFile(destFile, otherLocation);
while(!c1.ResponseHasArrived())
{
//... do something in the meanwhile
}
if (c1.IsSuccessful())
//show a success dialog
Проблема с этим третьим решением заключается в том, что вы не можете вернуться из функции вызывающего. Это делает его неподходящим, если работа, которую вы хотите выполнить между ними, не имеет ничего общего с работой, которую вы выполняете асинхронно. В течение долгого времени мне интересно, есть ли какая-то другая возможность вызывать функции асинхронно, та, у которой нет недостатков перечисленных выше опций. У кого-нибудь есть идея, может быть, какой-то умный трюк? 1037 *
Примечание: приведен пример псевдокода, подобного C ++. Тем не менее, я думаю, что этот вопрос в равной степени относится к C # и Java, и, возможно, ко многим другим языкам.