奥尔良提醒执行是否交错?

4

如果在同一粒子激活上有两个不同的提醒在同一时间点被触发,考虑到粒子执行上下文是单线程的,那么这两个提醒会被同时执行并交错吗?

另外,提醒执行是否受默认的30秒超时限制?

1个回答

7
提醒使用常规的粒度方法调用: IRemindable 接口是一个普通的粒度接口。IRemindable.ReceiveReminder(...) 没有标记为 [AlwaysInterleave],所以它只有在你的粒度类被标记为[Reentrant]时才会被交错执行。简而言之:默认情况下,提醒调用不会交错执行。
提醒不会覆盖 SiloMessagingOptions.ResponseTimeout 值,因此默认的执行时间为30秒。
如果您有一个提醒可能需要很长时间来执行,则可以遵循一个模式,在后台任务中启动长时间运行的工作,并确保当相关提醒触发时,该任务仍在运行(未完成或失败)。
以下是使用该模式的示例:
public class MyGrain : Grain, IMyGrain
{
    private readonly CancellationTokenSource _deactivating = new CancellationTokenSource();
    private Task _processQueueTask;
    private IGrainReminder _reminder = null;

    public Task ReceiveReminder(string reminderName, TickStatus status)
    {
        // Ensure that the reminder task is running.
        if (_processQueueTask is null || _processQueueTask.IsCompleted)
        {
            if (_processQueueTask?.Exception is Exception exception)
            {
                // Log that an error occurred.
            }

            _processQueueTask = DoLongRunningWork();
            _processQueueTask.Ignore();
        }

        return Task.CompletedTask;
    }

    public override async Task OnActivateAsync()
    {
        if (_reminder != null)
        {
            return;
        }

        _reminder = await RegisterOrUpdateReminder(
            "long-running-work",
            TimeSpan.FromMinutes(1),
            TimeSpan.FromMinutes(1)
        );
    }

    public override async Task OnDeactivateAsync()
    {
        _deactivating.Cancel(throwOnFirstException: false);

        Task processQueueTask = _processQueueTask;
        if (processQueueTask != null)
        {
            // Optionally add some max deactivation timeout here to stop waiting after (eg) 45 seconds

            await processQueueTask;
        }
    }

    public async Task StopAsync()
    {
        if (_reminder == null)
        {
            return;
        }
        await UnregisterReminder(_reminder);
        _reminder = null;
    }

    private async Task DoLongRunningWork()
    {
        // Log that we are starting the long-running work
        while (!_deactivating.IsCancellationRequested)
        {
            try
            {
                // Do long-running work
            }
            catch (Exception exception)
            {
                // Log exception. Potentially wait before retrying loop, since it seems like GetMessageAsync may have failed for us to end up here.
            }
        }
    }
}

1
长时间运行的工作不需要使用Task.Run或其他方式调用吗?否则它不是在谷物的调度程序上运行吗? - chillitom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接