C# блокировка ожидания ответа

Я много раз сталкивался с этой проблемой, в основном решал ее с помощью хаков, но хотел бы найти способ "пропрер" сделать это.

Я пишу протокол связи, очень похожий на RPC в том смысле, что мои конечные точки задают "запросы", на которые они получают "ответы".

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

Чтобы я мог сделать что-то вроде

int outside_temp = SendCommand(What is the temperature outside).ToInt();

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

Моя проблема с блокировкой потока. Блокировка потока не является проблемой, мы говорим о многопоточном приложении, чтобы пользовательский интерфейс не зависал и т. Д., Но вопрос в том, как правильно добиться этого?

Я думаю о чем-то вроде инициализации семафора внутри функции SendCommand, ожидания его и освобождения семафора в обработчике события полученного сообщения (после проверки, что это было правильное сообщение)?

С уважением, axos88

2 ответа

Решение

Таким образом, ваш вопрос о блокировке текущей ветки и ожидании ответа? Я бы использовал ManualResetEvent для синхронизации звонящего и обратного вызова.

Предполагается, что вы можете отправить свой вызов RPC через метод Send объекта, который принимает метод обратного вызова, вы можете кодировать свой SendCommand метод как это:

int SendCommand(int param)
{
    ManualResetEvent mre = new ManualResetEvent(false);

    // this is the result which will be set in the callback
    int result = 0;

    // Send an async command with some data and specify a callback method
    rpc.SendAsync(data, (returnData) =>
                       {
                           // extract / process your return value and 
                           // assign it to an outer scope variable
                           result = returnData.IntValue;
                           // signal the blocked thread to continue
                           mre.Set();
                       });

    // wait for the callback
    mre.WaitOne();
    return result;
}

Что вы можете сделать, это запустить новый поток, который вызывает SendCommand(..), и просто подождать, пока поток спит, пока ваш SendCommand не отправит сигнал.

Например:

volatile bool commandCompleted=false;
Thread sendCommandThread=new Thread(()=>{
   SendCommand(...,()=>{
 commandCompleted=true;
})

 while(!commandCompleted)
{

  Thread.Sleep(100);
}
});
Другие вопросы по тегам