Don't take a lock if there's no intention to manipulate the list of open streams. Instead, use a ConcurrentDictionary so that, in those situations, thread-safe access to the dictionary is ensured.
This commit is contained in:
parent
e92d8dd195
commit
4db5700e18
|
@ -1,6 +1,7 @@
|
|||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
@ -43,7 +44,7 @@ namespace Emby.Server.Implementations.Library
|
|||
private readonly ILocalizationManager _localizationManager;
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
|
||||
private readonly Dictionary<string, ILiveStream> _openStreams = new Dictionary<string, ILiveStream>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ConcurrentDictionary<string, ILiveStream> _openStreams = new ConcurrentDictionary<string, ILiveStream>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
private IMediaSourceProvider[] _providers;
|
||||
|
@ -582,29 +583,20 @@ namespace Emby.Server.Implementations.Library
|
|||
mediaSource.InferTotalBitrate();
|
||||
}
|
||||
|
||||
public async Task<IDirectStreamProvider> GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken)
|
||||
public Task<IDirectStreamProvider> GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
var info = _openStreams.Values.FirstOrDefault(i =>
|
||||
{
|
||||
var info = _openStreams.Values.FirstOrDefault(i =>
|
||||
var liveStream = i as ILiveStream;
|
||||
if (liveStream != null)
|
||||
{
|
||||
var liveStream = i as ILiveStream;
|
||||
if (liveStream != null)
|
||||
{
|
||||
return string.Equals(liveStream.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
return string.Equals(liveStream.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
return info as IDirectStreamProvider;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_liveStreamSemaphore.Release();
|
||||
}
|
||||
return Task.FromResult(info as IDirectStreamProvider);
|
||||
}
|
||||
|
||||
public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken)
|
||||
|
@ -793,29 +785,20 @@ namespace Emby.Server.Implementations.Library
|
|||
return new Tuple<MediaSourceInfo, IDirectStreamProvider>(info.MediaSource, info as IDirectStreamProvider);
|
||||
}
|
||||
|
||||
private async Task<ILiveStream> GetLiveStreamInfo(string id, CancellationToken cancellationToken)
|
||||
private Task<ILiveStream> GetLiveStreamInfo(string id, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(id));
|
||||
}
|
||||
|
||||
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
if (_openStreams.TryGetValue(id, out ILiveStream info))
|
||||
{
|
||||
if (_openStreams.TryGetValue(id, out ILiveStream info))
|
||||
{
|
||||
return info;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
return Task.FromResult(info);
|
||||
}
|
||||
finally
|
||||
else
|
||||
{
|
||||
_liveStreamSemaphore.Release();
|
||||
return Task.FromException<ILiveStream>(new ResourceNotFoundException());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -844,7 +827,7 @@ namespace Emby.Server.Implementations.Library
|
|||
|
||||
if (liveStream.ConsumerCount <= 0)
|
||||
{
|
||||
_openStreams.Remove(id);
|
||||
_openStreams.TryRemove(id, out _);
|
||||
|
||||
_logger.LogInformation("Closing live stream {0}", id);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user