0

I have a WebSocket implementation that initially was simple and short to mainly provide real time stock pricing information

            var updated = false;
            byte[] requestBuffer = new byte[1024 * 4];
            CancellationTokenSource cancellationToken = new CancellationTokenSource();
            while (webSocket.State == WebSocketState.Open || webSocket.State == WebSocketState.CloseSent)
            {
                var task = Task.Run(async () =>
                {
                    

                    while (webSocket.State == WebSocketState.Open)
                    {
                            someLongCodeHereToCalcualteThings...
                            
                            if (someCondition==true)
                            {

                                updated = true;

                            }
                        

                        if (updated)
                        {
                          data = getdata.......
                            requestBuffer = Encoding.ASCII.GetBytes(data);
                            var arraySegment = new ArraySegment<byte>(requestBuffer);
                            await webSocket.SendAsync(arraySegment, WebSocketMessageType.Text, true, cancellationToken.Token);
                            updated = false;
                        }
                        await Task.Delay(500, cancellationToken.Token);
                    }
                }, cancellationToken.Token);

                WebSocketReceiveResult result = await webSocket.ReceiveAsync(requestBuffer, cancellationToken.Token);

                if (result.MessageType == WebSocketMessageType.Close)
                {
                    await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken.Token);
                    break;
                }
            }
        }

But over the last few months the requirements grew, and I needed to retrieve some other WebSocket's dependents Realtime data, like real time positions data and orders data etc. which I implemented in their own standalone WebSockets, however it turned out to be a bad practice to create multiple WebSockets to cater for multiple real-time data items updated on the server especially that these data items need to be displayed on the same page on the client side.

My aim is to create an efficient task blocks for each real-time data function to trigger only one WebSocket SendAsync() when an update happen on either of the tasks

My real issue

When writing separate sub methods or tasks, I have a technical limitation knowing hoow the results of those methods can trigger the SendAsync() method within the Websocket's own task scope

What I tried:

I have created an asynchronous method for each subtask that update a related global variable which gets checked by the WebSocket implementation loop every second, if this global variable is update then this line gets executed

if(true)
{
    if(ordersUpdated || watchListUpdate || stockPricingUpdated)
    {
       if(ordersUpdated)
        {
         arraySegment = getOrdersData();

         await webSocket.SendAsync(arraySegment, WebSocketMessageType.Text, true, cancellationToken.Token);
         }

}
     Sleep(1000)
}

However this is really feels like an inefficient way of handling updates happening on different methods, so I'm trying to avoid running loops to monitor changes happening elsewhere.

The actual question is is there a way to execute the webSocket.SendAsync mehtod above every time an update happen on one of the subtasks methods?

Maya
  • 1,414
  • 5
  • 22
  • 43
  • Instead of mutating a global variable, you can use an Observable pattern where you register event handlers for curtain changes. – Eldar Oct 20 '22 at 06:57
  • Can you give me an example? because I tried event handlers above but I do not know how each event can trigger the SendAsync() method of the websocket (Im struggling to trigger the SendAsync() within the websocket task's scope) – Maya Oct 20 '22 at 07:00
  • Instead of implementing the `SendAsync` inside your receive/handling, you could create a public method which calls the SendAsync, so you are able to send messages from "anywhere". Sending and receiving can be called from different threads. (as long as you don't send from two threads concurrent. – Jeroen van Langen Oct 20 '22 at 07:02
  • The issue is SendAsync methods has to be within the the Websocket "while open.. scope" hence putting it elsewhere means I need the websocket to be implemented elsewhere too – Maya Oct 20 '22 at 07:06
  • Are you aware that you spin up a new (connection) task when a message is received? (because the task.run is inside the while loop. – Jeroen van Langen Oct 20 '22 at 08:12
  • No that's not how it works, only the code inside the second while is reiterated every 500 millisecond – Maya Oct 20 '22 at 11:24

0 Answers0