0

我正在尝试为 Websocketsharp 库实现请求/响应范例,它与 HttpClient 的请求/响应异步行为完全相同。我正在尝试使用下面代码中给出的异步回调来实现它。我试图让 SendAsync 方法的 OnMessage 回调事件等到服务器发送响应。我能够在 SendAsync 方法的范围内获得响应,但是一旦我们离开 SendAsync 范围,它就会清除响应的值。

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;
4

1 回答 1

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

        }

    }
于 2017-09-25T20:41:04.603 回答