Я работаю над проектом c#. Я хотел бы отправить запрос API через библиотеку websocketsharp каким-то синхронным способом.
Я пытался сделать это следующим образом:
Перед отправкой при любом запросе WS мы создаем новый объект SynchronousRequest () с уникальным идентификатором и добавляем вновь созданный объект в какой-то список ожидания
Мы отправляем запрос WS, добавляя уникальный идентификатор к полезной нагрузке, на ответ - сервер вернет тот же идентификатор.
Мы начинаем ждать сигнала события (сигнализация происходит после получения ответа)
В обработчике ответа:
Как только приходит ответ WS, я пытаюсь сопоставить контекст по уникальному идентификатору После совпадения мы сигнализируем событию, что ответ был получен, и добавляем полезную нагрузку ответа в объект synchronousRequest ()
Проблема - шаг 3, как только я использую WaitOne () в случае, когда весь клиент websocket зависает и больше не будет получено никаких ответов, что приведет к полной тупиковой ситуации.
Как я могу это сделать какой-то вызов WaitOne () в отдельном потоке или, возможно, существует полностью лучшее решение для моей проблемы, поэтому весь клиент не зависает, и мы сопоставляем контексты?
public class SynchronousRequest
{
public long requestId;
public ManualResetEvent resetEvent = new ManualResetEvent(false);
public dynamic response;
public SynchronousRequest()
{
var random = new Random();
requestId = random.Next();
}
}
public class APIWebSocket: BaseAPIWebSocket
{
private List<SynchronousRequest> waitingSyncRequests = new List<SynchronousRequest>();
public APIWebSocket()
{
ws = new WebSocket("wss://www.someserver.com");
registerConnectionEvents(); //Registers onOpen(), onMessage() handlers and similar
}
public void SendSyncTest()
{
var sr = new SynchronousRequest();
waitingSyncRequests.Add(sr);
//some data to send
var msg = new
{
jsonrpc = "2.0",
method = "public/ticker",
id = sr.requestId, //Response should contain the same ID
@params = new
{
instrument_name = "ETH"
}
};
ws.Send(JsonConvert.SerializeObject(msg));
//Below WaitOne() causes the entire websocket connection/thread to block
// No further messages will be received by HandleMessage() once we call WaitOne()
sr.resetEvent.WaitOne(); //Wait until we receive notification that response has been received
//do some processing on response here...
//Synchronous request completed, remove it from list
waitingSyncRequests.Remove(sr);
}
protected override void OnReceivedMessage(System.Object sender, WebSocketSharp.MessageEventArgs e)
{
dynamic message = JsonConvert.DeserializeObject(e.Data);
if (message.id != null )
{
//Find a resetEvent for given message.id
var matchingSyncRequest = waitingSyncRequests.First(r => r.requestId == message.id);
if (matchingSyncRequest != null)
{
matchingSyncRequest.response = message;
matchingSyncRequest.resetEvent.Set(); //Notify that response has been received
}
}
}
}