«Хранение» задания для последующего выполнения - PullRequest
2 голосов
/ 18 марта 2019

Я пытаюсь "сохранить" асинхронную задачу для последующего завершения - я нашел пример асинхронного кэша , но это эффективно приводит к кешированию результатов в параллельный словарь, так что их результаты могут быть перезагружены без повторного выполнения задачи (реализация HTML здесь ).

По сути, я пытаюсь создать словарь задач с ключами идентификаторами корреляции (GUID). Это для координации входящих результатов из другого места (XML идентифицируется идентификатором корреляции GUID), и моя цель - приостановить выполнение задачи до тех пор, пока результаты не поступят (вероятно, из очереди).

Это сработает? Это мой первый опыт правильного асинхронного кодирования, и я не могу найти ничего похожего на мое обнадеживающее решение, поэтому я вполне могу быть на правильном пути.

Могу ли я эффективно "сохранить" задачу для последующего завершения, при этом результат задачи будет установлен во время завершения?

Редактировать: Я только что узнал о TaskCompletionSource (на основе этот вопрос) это жизнеспособно?

Ответы [ 2 ]

2 голосов
/ 18 марта 2019

Если я правильно понимаю ваш вариант использования, вы можете использовать TaskCompletionSource.

Пример реализации:

public class AsyncCache
{
    private Dictionary<Guid, Task<string>> _cache;

    public Task<string> GetAsync(Guid guid)
    {
        if (_cache.TryGetValue(guid, out var task))
        {
            // The value is either there or already queued
            return task;
        }

        var tcs = new TaskCompletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);

        _queue.Enqueue(() => {
           var result = LoadResult();
           tcs.TrySetValue(result);
        });

        _cache.Add(guid, tcs.Task);

        return tcs.Task;            
    }
}

Здесь _queue - это любой механизм организации очередей, который вы собираетесь использовать для обработки данных. Конечно, вам также придется сделать этот код поточно-ориентированным.

2 голосов
/ 18 марта 2019

Вы думаете о ленивой загрузке? Вы можете использовать Lazy<Task> (который инициализирует задачу, но не ставит ее в очередь).

var tasks = new Dictionary<Guid, Lazy<Task>>();

tasks.Add(Task1Guid, new Lazy<Task>(() => { whatever the 1st task is }));
tasks.Add(Task2Guid, new Lazy<Task>(() => { whatever the 2nd task is }));


void async RunTaskAsync(Guid guid)
{
   await tasks[guid].Value;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...