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
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -43,7 +44,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
private readonly ILocalizationManager _localizationManager;
|
private readonly ILocalizationManager _localizationManager;
|
||||||
private readonly IApplicationPaths _appPaths;
|
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 readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
private IMediaSourceProvider[] _providers;
|
private IMediaSourceProvider[] _providers;
|
||||||
|
@ -582,29 +583,20 @@ namespace Emby.Server.Implementations.Library
|
||||||
mediaSource.InferTotalBitrate();
|
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);
|
var info = _openStreams.Values.FirstOrDefault(i =>
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var info = _openStreams.Values.FirstOrDefault(i =>
|
var liveStream = i as ILiveStream;
|
||||||
|
if (liveStream != null)
|
||||||
{
|
{
|
||||||
var liveStream = i as ILiveStream;
|
return string.Equals(liveStream.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase);
|
||||||
if (liveStream != null)
|
}
|
||||||
{
|
|
||||||
return string.Equals(liveStream.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
return info as IDirectStreamProvider;
|
return Task.FromResult(info as IDirectStreamProvider);
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_liveStreamSemaphore.Release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken)
|
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);
|
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))
|
if (string.IsNullOrEmpty(id))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(id));
|
throw new ArgumentNullException(nameof(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
if (_openStreams.TryGetValue(id, out ILiveStream info))
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (_openStreams.TryGetValue(id, out ILiveStream info))
|
return Task.FromResult(info);
|
||||||
{
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ResourceNotFoundException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally
|
else
|
||||||
{
|
{
|
||||||
_liveStreamSemaphore.Release();
|
return Task.FromException<ILiveStream>(new ResourceNotFoundException());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,7 +827,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
if (liveStream.ConsumerCount <= 0)
|
if (liveStream.ConsumerCount <= 0)
|
||||||
{
|
{
|
||||||
_openStreams.Remove(id);
|
_openStreams.TryRemove(id, out _);
|
||||||
|
|
||||||
_logger.LogInformation("Closing live stream {0}", id);
|
_logger.LogInformation("Closing live stream {0}", id);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user