我正在尝试实现WebSocketSharp库的请求/响应范式,它适用于HTTPCLCLIENT的Request/Response async行为。我正在尝试使用以下代码中给出的异步回调来实现它。我试图使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;
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);
}
}