Мое утверждение acceptor.IsStarted.Should().BeTrue();
(см. Модульный тест ниже) всегда терпит неудачу, так как оно оценивается слишком рано. Вызов await task
немедленно возвращается и не дает this.acceptor.Start()
достаточно времени для ускорения.
Я бы хотел запустить мой FixAcceptor()
more terministi c и для этого ввел параметр TimeSpan startupDelay
.
Однако я просто понятия не имею, где и как я могу отложить запуск.
Помещение дополнительных Thread.Sleep(startupDelay)
между this.acceptor.Start()
и this.IsStarted = true
не поможет, поскольку блокирует только саму рабочую задачу, но не вызывающий поток.
Надеюсь, понятно, что я хотел бы заархивировать и с чем борюсь. Заранее спасибо.
public class FixAcceptor
{
// Type provided by QuickFix.net
private readonly ThreadedSocketAcceptor acceptor;
public FixAcceptor(IFixSettings settings)
{
// Shortened
}
public bool IsStarted { get; private set; }
public async void Run(CancellationToken cancellationToken, TimeSpan startupDelay)
{
var task = Task.Run(() =>
{
cancellationToken.ThrowIfCancellationRequested();
this.acceptor.Start();
this.IsStarted = true;
while (true)
{
// Stop if token has been canceled
if (cancellationToken.IsCancellationRequested)
{
this.acceptor.Stop();
this.IsStarted = false;
cancellationToken.ThrowIfCancellationRequested();
}
// Save some CPU cycles
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}, cancellationToken);
try
{
await task;
}
catch (OperationCanceledException e)
{
Debug.WriteLine(e.Message);
}
}
}
и соответствующий код потребителя
[Fact]
public void Should_Run_Acceptor_And_Stop_By_CancelationToken()
{
// Arrange
var acceptor = new FixAcceptor(new FixAcceptorSettings("test_acceptor.cfg", this.logger));
var tokenSource = new CancellationTokenSource();
// Act
tokenSource.CancelAfter(TimeSpan.FromSeconds(10));
acceptor.Run(tokenSource.Token, TimeSpan.FromSeconds(3));
// Assert
acceptor.IsStarted.Should().BeTrue();
IsListeningOnTcpPort(9823).Should().BeTrue();
// Wait for cancel event to occur
Thread.Sleep(TimeSpan.FromSeconds(15));
acceptor.IsStarted.Should().BeFalse();
}