Add support for exclusive mode

This commit is contained in:
Patrik Svensson
2021-03-13 22:45:31 +01:00
committed by Phil Scott
parent c2bab0ebf8
commit 7f6f2437b1
26 changed files with 351 additions and 128 deletions

View File

@ -13,9 +13,10 @@ namespace Spectre.Console
public Profile Profile { get; }
public IAnsiConsoleCursor Cursor => GetBackend().Cursor;
public IAnsiConsoleInput Input { get; }
public IExclusivityMode ExclusivityMode { get; }
public RenderPipeline Pipeline { get; }
public AnsiConsoleFacade(Profile profile)
public AnsiConsoleFacade(Profile profile, IExclusivityMode exclusivityMode)
{
_renderLock = new object();
_ansiBackend = new AnsiConsoleBackend(profile);
@ -23,6 +24,7 @@ namespace Spectre.Console
Profile = profile ?? throw new ArgumentNullException(nameof(profile));
Input = new DefaultInput(Profile);
ExclusivityMode = exclusivityMode ?? throw new ArgumentNullException(nameof(exclusivityMode));
Pipeline = new RenderPipeline();
}

View File

@ -1,4 +1,3 @@
using System.Linq;
using Spectre.Console.Rendering;
using Wcwidth;

View File

@ -0,0 +1,57 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Spectre.Console.Internal
{
internal sealed class DefaultExclusivityMode : IExclusivityMode
{
private static readonly SemaphoreSlim _semaphore;
static DefaultExclusivityMode()
{
_semaphore = new SemaphoreSlim(1, 1);
}
public T Run<T>(Func<T> func)
{
// Try aquiring the exclusivity semaphore
if (!_semaphore.Wait(0))
{
throw new InvalidOperationException(
"Trying to run one or more interactive functions concurrently. " +
"Operations with dynamic displays (e.g. a prompt and a progress display) " +
"cannot be running at the same time.");
}
try
{
return func();
}
finally
{
_semaphore.Release(1);
}
}
public async Task<T> Run<T>(Func<Task<T>> func)
{
// Try aquiring the exclusivity semaphore
if (!await _semaphore.WaitAsync(0).ConfigureAwait(false))
{
// TODO: Need a better message here
throw new InvalidOperationException(
"Could not aquire the interactive semaphore");
}
try
{
return await func();
}
finally
{
_semaphore.Release(1);
}
}
}
}