Я разрабатываю консольное приложение, в котором есть сторонний клиент rest (точнее, клиент wordpress rest), в котором есть некоторые методы с объектами return Task
. Пример сигнатуры метода может быть такой:
public Task<bool> Delete(int id);
У меня есть список Post
, который нужно удалить. Я мог бы сделать что-нибудь просто вроде:
public void DeleteGivenPosts(List<Post> posts) {
posts.ForEach(async post => await wpRestClient.Delete(post.Id));
}
В этом случае удаление выполняется и забывает. Будет лучше, если я внесу в журнал информацию об удаленном посте. Оператор журнала, например:
logger.Log($"A post with {post.Id} is deleted");
Итак, я решил спроецировать Задачи.
public async Task DeleteGivenPosts(List<Post> posts) {
var postDeletionTasks = posts.Select(post => wpRestClient.Delete(post.Id));
foreach (var deletionTask in TaskExtensionUtil.GetTasksInCompletingOrder(postsDeletionTasks)) {
bool deletionResult = await deletionTask;
if(deletionResult) {
//i want to log success of deletion here
} else {
//i want to log the failure of deletion here
}
}
}
Здесь TaskExtensionUtil.GetTasksInCompletingOrder()
- это вспомогательный метод, который возвращает задачи в порядке их выполнения. Код для этого:
public static List<Task<T>> GetTasksInCompletingOrder<T>(IEnumerable<Task<T>> sourceTasks) {
var sourceTasksArr = sourceTasks.ToArray();
var taskCompletionSourceArr = new TaskCompletionSource<T>[sourceTasksArr.Length];
var currentSlot = -1;
for (int i = 0; i < sourceTasksArr.Length; i++) {
taskCompletionSourceArr[i] = new TaskCompletionSource<T>();
sourceTasksArr[i].ContinueWith(prev => {
int indexToSet = Interlocked.Increment(ref currentSlot);
taskCompletionSourceArr[indexToSet].SetResult(prev.Result);
});
}
return taskCompletionSourceArr.Select(i => i.Task).ToList();
}
Проблема в том, что deletionResult
- это bool
. Чтобы регистрировать информацию о том, какой пост был удален, мне нужно получить объект Post
, связанный с задачей удаления.
Я думал создать словарь, который сопоставляет задачу удаления с соответствующим Post
, выполнив что-то вроде:
posts.Select(post => new { deletionTask = wpRestClient.Delete(post.Id), post})
.ToDictionary(i => i.deletionTask, i => i.post);
Но это не сработает, потому что в GetTasksInCompletingOrder
исходные задачи удаления переведены в TaskCompletionSource
задач. Так что я всегда получаю исключение, что ключа нет в словаре. Также я не уверен, как будет вести себя словарь, если в качестве ключей он имеет Task
объектов.
На данный момент я не знаю, как добиться ведения журнала. Буду признателен за любую помощь.