3

我有一个ReliableQueue<MyTask>被排入不同范围的队列,并且我正在将事务中的任务出列,然后想对每个任务运行一些长时间运行的计算。

这里的问题是,如果我的队列事务被中止,我不想丢失长计算的实例。它将继续在后台独立运行,我只想在我重试处理任务后检查它是否完成。

代码段:

public void protected override async Task RunAsync(CancellationToken cancellationToken)
{
    var queue = await StateManager.GetOrAddAsync<IReliableQueue<MyTask>>(...);
    while(!cancellationToken.IsCancellationRequested)
    {
        using (var transaction = ...)
        {
            var myTaskConditional = await queue.TryDequeueAsync(transaction);
            if (!myTaskConditional.HasValue)
            {
                break;
            }
            await DoLongProcessing(myTaskConditional)
            await transaction.CommitAsync();
        }
    }
}

private async void DoLongProcessing(MyTask myTask) {
    var dict = await StateManager.GetOrAddAsync<IReliableDictionary<Guid,Guid>>(...);
    Conditional<Guid> guidConditional;
    using (var transaction = ...)
    {
        guidConditional = await dict.TryGetValueAsync(myTask.TaskGuid);
        if (guidConditional.HasValue) {
            await transaction.CommitAsync();
            // continue handling knowing we already started, continue to wait for 
            await WaitForClaulcationFinish(guidConditional.Value);
        }
        else {
            // start handling knowing we never handled this task, create new guid and store it in dict
            var runGuid = await StartRunningCalculation(runGuid);
            await dict.AddAsync(myTask.TaskGuid, runGuid);
            await transaction.CommitAsync();
            await WaitForClaulcationFinish(runGuid);
        }
    }
}

我的担忧:我正在使用嵌套事务,不建议这样做。

如果我仅将事务用于ReliableQueueReliableDictionary单独使用,这里是否真的存在死锁的风险?

对于我想要实现的目标,是否有更好的设计?

4

1 回答 1

1

您不应该在事务中长时间运行任何事情。看看我发布的优先队列服务。在工作时将项目从队列中取出并将其放入集合中,然后在完成后将其放回队列或完成工作。

于 2017-05-29T15:38:53.327 回答