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);
}
});