2017-09-22 3 views
0

Ich versuche, Request/Response-Paradigma für WebSocketSharp-Bibliothek genau dasselbe implementieren funktioniert es für HttpClient Anfrage/Antwort-Async-Verhalten. Ich versuche es zu erreichen, indem ich den Async-Callback verwende, wie er in dem folgenden Code angegeben ist. Ich habe versucht, das OnMessage-Rückrufereignis der SendAsync-Methode abzuwarten, bis der Server die Antwort sendet. Ich kann die Antwort im Rahmen der SendAsync-Methode abrufen, löscht jedoch den Wert der Antwort, sobald wir den SendAsync-Bereich verlassen haben.Request/Response-Paradigma für WebSocketsharp-Bibliothek mit Websocket.SendAsync() und OnMessage Callback-Funktion

string clientResponse = null; 

      var response = Task.Run(() => objWSClient.SendAsync(stream, Convert.ToInt32(stream.Length), (async (completed) => 
      { 
       if (completed) 
       { 
        clientResponse = await WSMessageSendSuccess(reqObject, callback); 

        // Websocket response is flushed to the console window, but when it leaves the scope, it doesn't hold the response out of the SendAsync() scope. 
        Console.WriteLine(clientResponse); 
       } 
       else 
       { 
        WSMessageSendFail(reqObject); 
        clientResponse = "Failure to send Message"; 
       } 
      }))); 


      while (response.Status != TaskStatus.RanToCompletion) 
      { 
       Task.Delay(10000).Wait(); 
      } 
      response.Wait(); 

      // As soon as we leave scope of WebSocket.SendAsync() method, it clears the client response variable value. 
      // variable name : clientResponse;, it also works same with static property/variable. 
      return clientResponse; 
+0

Sie die API von folgenden Microsoft-Artikel einkapseln kann, https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/interop-with-other-asynchronous -Patterns-und-Typen # Aufgaben-und-das-Ereignis-basierte-asynchrone-Muster-eap –

Antwort

0
static Class WSClient{ 


     Private Dictionary <string, Func<string, void>> DictWSReqResp = new Dictionary <string, Func<string, void>>(); 
     Private WebSocket objWSClient; 


     public static void init(Iconfiguration config){ 
      //instantiate objWSClient here, set all handlers, and connect 
      objWSClient.OnMessage += new EventHandler<MessageEventArgs>(e_ServerMessageReceived); 
     } 




     async Task<String> Request(uri, method, payload, headers){ 

      //it is important that this be an async function and the return be an await, because this way we 
      //guarantee that the taskCS remains in scope of this function. If this were to return the task itself 
      //then the tcs will be subject to GC. 

      //the three variables below will remain alive while the task is not completed 
      TaskCompletionSource<string> taskCS = new TaskCompletionSource<string>(); 
      string trackid = trackid; 
      Action<string> callback; 

      //the sendAsync callback should NOT be async 
      objWSClient.SendAsync(stream, Convert.ToInt32(stream.Length), new Action<bool>(completed) => 
      { 
       if (completed) 
       { 
        callback = (payload)=>{ //this will not run unless called by the e_ServerMessageReceived handler 
         taskCS.SetResult(payload); 
         DictWSReqResp.delete(trackid); 
        } 
        DictWSReqResp.Add(trackid, callback); 
       } 
       else 
       { 
        //create well formed errorPayload 
        taskCS.SetException(errorPayload); 
       } 
      }); 



      return await taskCS.Task; 


     } 



     private static void e_ServerMessageReceived(payload){ //server sends {t:1 /*for responses*/, i:<trackid>, p:<response payload>} 
      if(t==1)(DictWSReqResp(payload.i))(payload.p); 

     } 

    } 
+0

Sorry für die Hässlichkeit. Dies ist meine Lösung für das gleiche Problem wie Ihres. Die Serverantwort ist ein JSON-Objekt, in dem payload.i auf die Track-ID gesetzt ist. Der Rest ist selbsterklärend. –

+0

Es fehlt auch ein bisschen Logik. Meine Klasse konvertiert eine REST-Nachricht in eine WS-Nutzlast. –

Verwandte Themen