public async Task<bool> TrySwitchBrokerAsync(string name, string path = null, CancellationToken cancellationToken = default(CancellationToken)) {
using (_disposeToken.Link(ref cancellationToken)) {
await TaskUtilities.SwitchToBackgroundThread();
var brokerClient = CreateBrokerClient(name, path, cancellationToken);
if (brokerClient == null) {
return false;
}
// Broker switching shouldn't be concurrent
IAsyncReaderWriterLockToken lockToken;
try {
lockToken = await _connectArwl.WriterLockAsync(cancellationToken);
} catch (OperationCanceledException) {
brokerClient.Dispose();
return false;
}
if (brokerClient.Name.EqualsOrdinal(_brokerProxy.Name) &&
brokerClient.Uri.AbsoluteUri.PathEquals(_brokerProxy.Uri.AbsoluteUri)) {
brokerClient.Dispose();
try {
// Switching to the broker that is currently running and connected is always successful
if (IsConnected) {
return true;
}
await ReconnectAsync(cancellationToken);
} catch (Exception) {
return false;
} finally {
lockToken.Dispose();
}
IsConnected = true;
return true;
}
// First switch broker proxy so that all new sessions are created for the new broker
var oldBroker = _brokerProxy.Set(brokerClient);
if (_updateHostLoadLoopTask == null) {
_updateHostLoadLoopTask = UpdateHostLoadLoopAsync();
}
try {
BrokerChanging?.Invoke(this, EventArgs.Empty);
await SwitchBrokerAsync(cancellationToken);
oldBroker.Dispose();
} catch (Exception ex) {
_brokerProxy.Set(oldBroker);
if (_disposeToken.IsDisposed) {
oldBroker.Dispose();
}
brokerClient.Dispose();
BrokerChangeFailed?.Invoke(this, EventArgs.Empty);
if (ex is OperationCanceledException || ex is RHostBrokerBinaryMissingException) {
// RHostDisconnectedException is derived from OperationCanceledException
return false;
}
throw;
} finally {
lockToken.Dispose();
}
IsConnected = true;
OnBrokerChanged();
return true;
}
}