_sendTicketCurrent
должен быть изменчивым, в противном случае JIT разрешено кэшировать значение в регистре, что может привести к бесконечному циклу.Кроме того, он выглядит поточно-безопасным, за исключением того, что это огромная трата процессора (SpinWait полностью использует ядро).
Также нет смысла делать await Task.Run(() => SpinWait.SpinUntil(() => mySendTicket == _sendTicketCurrent))
.Вы все равно будете удерживать поток, так что вы можете сделать ожидание в текущем потоке.
Чтобы сделать то, что вы хотите, более оптимизированным способом, уже есть асинхронно-совместимый примитив синхронизации, предоставленный изкоробка: SemaphoreSlim.
private SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
public async Task SendAsync(string message)
{
if (_ws.State != WebSocketState.Open)
throw new Exception("Connection is not open");
try
{
await _semaphore.WaitAsync().ConfigureAwait(false);
var cancel = new CancellationTokenSource(5000);
var bytes = new ArraySegment<byte>(Encoding.UTF8.GetBytes(message));
await _ws.SendAsync(bytes, WebSocketMessageType.Text, true, cancel.Token).ConfigureAwait(false);
}
finally
{
_semaphore.Release();
}
}