Попробуйте что-то вроде
ConcurrentDictionary<Guid, (System.Byte[], WebSocketReceiveResult)> x = new ConcurrentDictionary<Guid, (byte[], WebSocketReceiveResult)>();
Создайте GUID в вашем foreach и передайте его вашим методам:
foreach (var request in handshake.AutheticateStrings)
{
var buffer = _encoder.GetBytes(request);
var guid = Guid.NewGuid();
await Task.WhenAll(Receive(_webSocket, guid), Send(_webSocket, buffer, guid));
}
Затем вы можете работать со словарем из ваших методов получения и отправки вестественным путем.
void Send(WebSocket webSocket, byte[] buffer, Guid guid)
{
x.GetOrAdd(guid, new ValueTuple<System.Byte[], WebSocketReceiveResult>(buffer, null));
await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None)
}
void Receive(WebSocket webSocket, Guid guid)
{
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
x[guid].Item2 = result;
}