I am developing a console application in which I have a third party rest client (wordpress rest client to be precise), which has some methods with return Task
objects. An example method signature can be like:
public Task<bool> Delete(int id);
I have a list of Post
to be deleted. I could do something simply like:
public void DeleteGivenPosts(List<Post> posts) {
posts.ForEach(async post => await wpRestClient.Delete(post.Id));
}
In this case the deletion is fire and forget. It would be better if I log the information about the post which is deleted. A log statement like:
logger.Log($"A post with {post.Id} is deleted");
So, I decided to project the Tasks.
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
}
}
}
Here TaskExtensionUtil.GetTasksInCompletingOrder()
is a helper method which returns the tasks in the order they complete. Code for this is:
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();
}
The problem is that the deletionResult
is a bool
. In order to log information about which post is deleted I need to get the Post
object associated with the deletion task.
I was thinking to create a dictionary that maps the deletion task to the corresponding Post
by doing something like:
posts.Select(post => new { deletionTask = wpRestClient.Delete(post.Id), post})
.ToDictionary(i => i.deletionTask, i => i.post);
But this will not work because in the GetTasksInCompletingOrder
the original deletion tasks are translated to TaskCompletionSource
tasks. So I will always get an exception that the key is not present in the dictionary. Also I am not sure how will a dictionary behave when it has Task
objects as keys.
At this point I have no clue how to achieve the logging. I will appreciate any help.