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);
        }
    }
}

私の懸念: ネストされたトランザクションを使用していますが、これはお勧めできません。

ReliableQueueトランザクションを単独またはReliableDictionary個別に使用している場合、実際にデッドロックのリスクはありますか?

私が達成しようとしていることに対して、より適切な設計はありますか?

4

1 に答える 1