C# 在下面的场景中,如何将自定义对象映射到相应的任务?

C# 在下面的场景中,如何将自定义对象映射到相应的任务?,c#,async-await,task,task-parallel-library,C#,Async Await,Task,Task Parallel Library,我正在开发一个控制台应用程序,其中有一个第三方rest客户端wordpress rest client,确切地说,它有一些带有返回任务对象的方法。示例方法签名可以类似于: public Task<bool> Delete(int id); 在这种情况下,删除是fire and forget。如果我把被删除的帖子的信息记录下来会更好。日志语句,如: logger.Log($"A post with {post.Id} is deleted"); 因此,我决定对这些任务进行规划 pu

我正在开发一个控制台应用程序,其中有一个第三方rest客户端wordpress rest client,确切地说,它有一些带有返回任务对象的方法。示例方法签名可以类似于:

public Task<bool> Delete(int id);
在这种情况下,删除是fire and forget。如果我把被删除的帖子的信息记录下来会更好。日志语句,如:

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
    }
  }
}
问题是deletionResult是一个bool。为了记录关于删除哪个帖子的信息,我需要获取与删除任务关联的帖子对象

我想创建一个字典,通过如下操作将删除任务映射到相应的帖子:

posts.Select(post => new { deletionTask = wpRestClient.Delete(post.Id), post})
     .ToDictionary(i => i.deletionTask, i => i.post);
private async Task<DeletionResult> DeletePost(int postId)
{
    bool result = await wpRestClient.Delete(postId);
    return new DeletionResult(result, postId);
}
但这将不起作用,因为在GetTaskCompletingOrder中,原始删除任务被转换为TaskCompletionSource任务。因此,我总是会得到一个例外,即字典中没有该键。此外,我也不确定当字典将任务对象作为键时,它将如何工作


在这一点上,我不知道如何实现日志记录。我将非常感谢您的帮助。

删除后如何编写日志语句

public async Task DeleteGivenPosts(List<Post> posts)
{
    await Task.WhenAll(
    posts.Select(async post =>
    {
        bool res = await wpRestClient.Delete(post.Id);
        string message = res ? $"Post {post.Id} is deleted" : $"Post {post.Id} survived!";
        logger.Log(message);
    }));
}
下面是一个小型LinqPad程序,用于举例说明该方法的工作原理:

async void Main()
{
    List<Post> postList = Enumerable.Range(1, 12).Select(id => new Post {Id = id}).ToList();
    Console.WriteLine("Start Deletion");
    await DeleteGivenPosts(postList);
    Console.WriteLine("Finished Deletion");
}

public static MyRestClient wpRestClient = new MyRestClient();
// Define other methods and classes here
public async Task DeleteGivenPosts(List<Post> posts)
{
    await Task.WhenAll(
    posts.Select(async post =>
    {
        bool res = await wpRestClient.Delete(post.Id);
        string message = res ? $"Post {post.Id} is deleted" : $"Post {post.Id} survived!";
        Console.WriteLine(message);
    }));
}

public static Random rand = new Random(DateTime.Now.Millisecond);

public class MyRestClient
{
    public async Task<bool> Delete(int i)
    {
        return await Task<bool>.Run(() => { Thread.Sleep(400); return rand.Next(1,4) == 1;});
    }
}

public class Post
{
    public int Id { get; set; }
}
输出:

开始删除 1号帖子被删除 3号柱幸存了! 5号柱幸存了! 6号柱幸存了! 2号哨所幸免于难! 4号柱幸存了! 8号柱幸存了! 邮政7幸存! 9号柱幸存了! 11号岗位幸存了! 第10条被删除 第12条被删除 完成删除


删除后写logstatement怎么样

public async Task DeleteGivenPosts(List<Post> posts)
{
    await Task.WhenAll(
    posts.Select(async post =>
    {
        bool res = await wpRestClient.Delete(post.Id);
        string message = res ? $"Post {post.Id} is deleted" : $"Post {post.Id} survived!";
        logger.Log(message);
    }));
}
下面是一个小型LinqPad程序,用于举例说明该方法的工作原理:

async void Main()
{
    List<Post> postList = Enumerable.Range(1, 12).Select(id => new Post {Id = id}).ToList();
    Console.WriteLine("Start Deletion");
    await DeleteGivenPosts(postList);
    Console.WriteLine("Finished Deletion");
}

public static MyRestClient wpRestClient = new MyRestClient();
// Define other methods and classes here
public async Task DeleteGivenPosts(List<Post> posts)
{
    await Task.WhenAll(
    posts.Select(async post =>
    {
        bool res = await wpRestClient.Delete(post.Id);
        string message = res ? $"Post {post.Id} is deleted" : $"Post {post.Id} survived!";
        Console.WriteLine(message);
    }));
}

public static Random rand = new Random(DateTime.Now.Millisecond);

public class MyRestClient
{
    public async Task<bool> Delete(int i)
    {
        return await Task<bool>.Run(() => { Thread.Sleep(400); return rand.Next(1,4) == 1;});
    }
}

public class Post
{
    public int Id { get; set; }
}
输出:

开始删除 1号帖子被删除 3号柱幸存了! 5号柱幸存了! 6号柱幸存了! 2号哨所幸免于难! 4号柱幸存了! 8号柱幸存了! 邮政7幸存! 9号柱幸存了! 11号岗位幸存了! 第10条被删除 第12条被删除 完成删除


你也可以用你自己的方法来包装它,比如:

IEnumerable<Task<DeletionResult>> postDeletionTasks = posts.Select(post => DeletePost(post.Id));

这样,您将有一个任务列表,其结果包含受影响的PostId。

您也可以使用自己的方法将其包装起来,如下所示:

IEnumerable<Task<DeletionResult>> postDeletionTasks = posts.Select(post => DeletePost(post.Id));


这样,您将有一个任务列表,其结果包含受影响的PostId。

@NavjotSingh这意味着您需要一个等待的方法DeleteGivenPosts?还是希望用户阻止关闭您的应用程序?我必须确保在所有删除任务完成之前,应用程序不会退出。顺便问一下,在你的linqPad程序中,主方法是否会等待所有帖子被删除?不,不会,因为你的DeleteGivenPosts方法无效是的,那么我想我需要一个等待的方法。@NavjotSingh好的,那么我很高兴我们解决了你的问题。祝您有个美好的一天mate@NavjotSingh这意味着你需要一个等待的方法来删除GivenPosts?还是希望用户阻止关闭您的应用程序?我必须确保在所有删除任务完成之前,应用程序不会退出。顺便问一下,在你的linqPad程序中,主方法是否会等待所有帖子被删除?不,不会,因为你的DeleteGivenPosts方法无效是的,那么我想我需要一个等待的方法。@NavjotSingh好的,那么我很高兴我们解决了你的问题。祝你有愉快的一天,你是什么意思?我正在等待删除,但没有等待.posts.Select中的DeletePost,不确定我是否理解你的意思。我错误地理解了你的答案。我的错。我认为你的回答也解决了问题。你是什么意思?我正在等待删除,但没有等待.posts.Select中的DeletePost,不确定我是否理解你的意思。我错误地理解了你的答案。我的错。我认为你的答案也解决了问题。你真的想像火一样运行删除并忘记任务吗?@TheodorZoulias我只想执行删除。如果有失败,我只想告诉你,某个删除无法完成。我不清楚你是否故意解雇并忘记删除,因为你不在乎他们在那一刻是成功还是失败,或者你是无意中这样做的,因为你不知道如何等待他们完成后再继续。是的,我刚刚注意到,接受的答案包含使用Task.WhenAll的DeleteGivenPosts的正确版本。它还包含使用List.ForEach方法的有问题的DeleteGivenPosts。这是相当令人困惑的,因为有问题的版本位于顶部,而正确的版本是作为如何使用有问题版本的假定示例呈现的。不管怎样,你的问题现在解决了,所以一切都很好-@TheodorZoulias感谢您的评论。我从顶部删除了DeleteGivenPosts的令人困惑的问题版本,并将其与下面程序中的异步版本进行了交换。您真的想将删除作为fire and forget tasks运行吗?@TheodorZoulias我只想执行删除。如果有fai
lure我只想告诉你,某个删除无法完成。我不清楚你是否故意解雇并忘记删除,因为你不在乎他们在那一刻是成功还是失败,或者你是无意中这样做的,因为你不知道如何等待他们完成后再继续。是的,我刚刚注意到,接受的答案包含使用Task.WhenAll的DeleteGivenPosts的正确版本。它还包含使用List.ForEach方法的有问题的DeleteGivenPosts。这是相当令人困惑的,因为有问题的版本位于顶部,而正确的版本是作为如何使用有问题版本的假定示例呈现的。不管怎样,你的问题现在解决了,所以一切都很好-@TheodorZoulias感谢您的评论。我从顶部删除了DeleteGivenPosts这个令人困惑的有问题的版本,并将其与下面程序中的异步版本进行了交换。