48 lines
1.6 KiB
C#
48 lines
1.6 KiB
C#
namespace Monitor.Measurement;
|
|
|
|
/// <summary>一个运行中的积木:自己的取消令牌和后台任务。Probe 和 Agent 共用。</summary>
|
|
public sealed class RunningBlock : IDisposable
|
|
{
|
|
private readonly CancellationTokenSource _cts = new();
|
|
|
|
private RunningBlock(IBlock block, string signature)
|
|
{
|
|
Block = block;
|
|
Signature = signature;
|
|
Completion = Task.CompletedTask;
|
|
}
|
|
|
|
public IBlock Block { get; }
|
|
|
|
/// <summary>参数、端口或流编号变化时调和器据此重启积木。</summary>
|
|
public string Signature { get; }
|
|
|
|
/// <summary>积木自己结束(单向数据流的发送端)或失败(<see cref="BlockFaultException"/>)时完成;被 <see cref="StopAsync"/> 停止时正常完成。</summary>
|
|
public Task Completion { get; private set; }
|
|
|
|
public static RunningBlock Start(IBlock block, string signature)
|
|
{
|
|
var running = new RunningBlock(block, signature);
|
|
running.Completion = Task.Run(() => block.RunAsync(running._cts.Token), CancellationToken.None);
|
|
return running;
|
|
}
|
|
|
|
/// <summary>停止积木并等它退出(最多 5 秒)。</summary>
|
|
public async Task StopAsync()
|
|
{
|
|
await _cts.CancelAsync();
|
|
try
|
|
{
|
|
await Completion.WaitAsync(TimeSpan.FromSeconds(5));
|
|
}
|
|
catch (Exception ex) when (ex is OperationCanceledException or TimeoutException or BlockFaultException)
|
|
{
|
|
// 没有及时退出或者已经失败:不再等
|
|
}
|
|
|
|
Dispose();
|
|
}
|
|
|
|
public void Dispose() => _cts.Dispose();
|
|
}
|