I'm working on c# project. I'd like to send API request via websocketsharp library in some sort of synchronous way.
I've been trying to do it following way:
Before we send any WS request , we create new SynchronousRequest() object with unique ID and add the newly created object to some sort of waiting list
We send WS request adding unique ID to the payload, on the response - the server will return the same id.
We start waiting for the event to be signaled (signaling happens once we receive response)
On the response handler:
- Once WS response arrives, I try to match the context by the unique ID
- Once it's matched, we signal event that the response has been received and add the response payload to the the synchronousRequest() object
Problem is step 3, once i use WaitOne() on the event the entire websocket client hangs and no further responses will be received - resulting in complete deadlock.
How can i do some sort of WaitOne() call in seperate thread or perhaps completely better solution exists for my problem, so the entire client does not hang and we match the contexts?
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
}
}
}
}