private async static void OnKeepAlive(object sender)
{
Debug.Assert(sender != null, "'sender' MUST NOT be NULL.");
Debug.Assert((sender as WebSocketBase) != null, "'sender as WebSocketBase' MUST NOT be NULL.");
WebSocketBase thisPtr = sender as WebSocketBase;
bool lockTaken = false;
if (NetEventSource.IsEnabled)
{
NetEventSource.Enter(thisPtr);
}
CancellationToken linkedCancellationToken = CancellationToken.None;
try
{
Monitor.Enter(thisPtr.SessionHandle, ref lockTaken);
if (thisPtr._isDisposed ||
thisPtr._state != WebSocketState.Open ||
thisPtr._closeOutputTask != null)
{
return;
}
if (thisPtr._keepAliveTracker.ShouldSendKeepAlive())
{
bool ownsCancellationTokenSource = false;
try
{
ownsCancellationTokenSource = thisPtr._sendOutstandingOperationHelper.TryStartOperation(CancellationToken.None, out linkedCancellationToken);
if (ownsCancellationTokenSource)
{
thisPtr.EnsureKeepAliveOperation();
thisPtr._keepAliveTask = thisPtr._keepAliveOperation.Process(null, linkedCancellationToken);
ReleaseLock(thisPtr.SessionHandle, ref lockTaken);
await thisPtr._keepAliveTask.SuppressContextFlow();
}
}
finally
{
if (!lockTaken)
{
Monitor.Enter(thisPtr.SessionHandle, ref lockTaken);
}
thisPtr._sendOutstandingOperationHelper.CompleteOperation(ownsCancellationTokenSource);
thisPtr._keepAliveTask = null;
}
thisPtr._keepAliveTracker.ResetTimer();
}
}
catch (Exception exception)
{
try
{
thisPtr.ThrowIfConvertibleException(nameof(OnKeepAlive),
exception,
CancellationToken.None,
linkedCancellationToken.IsCancellationRequested);
throw;
}
catch (Exception backgroundException)
{
thisPtr.OnBackgroundTaskException(backgroundException);
}
}
finally
{
ReleaseLock(thisPtr.SessionHandle, ref lockTaken);
if (NetEventSource.IsEnabled)
{
NetEventSource.Exit(thisPtr);
}
}
}