C# 有没有办法在并行任务完成后立即访问这些任务的结果?

C# 有没有办法在并行任务完成后立即访问这些任务的结果?,c#,.net,xamarin,C#,.net,Xamarin,目前,我并行运行多个任务,并将结果放在一个列表中,从中使用数据。 我想并行运行我的所有任务,但一旦其中一个任务完成,就可以直接访问它的数据 这是我目前的代码: await Task.Run(async () => { Parallel.For(0, k, i => { var tt = Sites.oneNews(cat, sites[i]);

目前,我并行运行多个任务,并将结果放在一个列表中,从中使用数据。 我想并行运行我的所有任务,但一旦其中一个任务完成,就可以直接访问它的数据

这是我目前的代码:

await Task.Run(async () =>
            {
                Parallel.For(0, k, i =>
                {
                    var tt = Sites.oneNews(cat, sites[i]);
                    results.Add(tt.Result);
                });
            });

我迫不及待地想把它们全部做完,因为有些花的时间太长了。我需要在结果单独返回后立即访问它

我建议您阅读它-它帮助我在我的一个项目中实现了一个通用逻辑,并且也是dotnet文档推荐的(我还将链接帮助我找到该资源的C).

我建议您阅读这篇文章-它帮助我在我的一个项目中实现了一个通用逻辑,并且也是dotnet文档推荐的(我还将链接帮助我找到该资源的C).

如果不确切知道您在什么上下文中使用此代码,我可以说您不需要使用async关键字,因为您正在运行的操作不是异步的。在任何情况下,如果您需要处理任何集合更改事件,那么您可以使用
ObservableCollection
监听任何
CollectionChanged
事件并处理添加的
tt.Result
。但请记住,由于您使用的是并行性,这意味着由于您的代码不是异步的,因此每个循环都应该在同一时刻完成(取决于操作的强度)。同样,我不知道确切的上下文,所以我不能多说。

如果不确切知道您在什么上下文中使用此代码,我可以说您不需要使用async关键字,因为您正在运行的操作不是异步的。在任何情况下,如果您需要处理任何集合更改事件,那么您可以使用
ObservableCollection
监听任何
CollectionChanged
事件并处理添加的
tt.Result
。但请记住,由于您使用的是并行性,这意味着由于您的代码不是异步的,因此每个循环都应该在同一时刻完成(取决于操作的强度)。同样,我不知道确切的上下文,所以我不能多说。

只需制作
结果
这样的线程安全的生产者-消费者集合。它有
getconsumineGenumerable
方法,该方法返回一个IEnumerable,该IEnumerable将在另一个代码部分将项添加到集合中时立即生成该项

var results = new BlockingCollection<Result>();

async Task ProducerAsync()
{
  await Task.Run(() => // I removed the async here as it was not needed
  {
    Parallel.For(0, k, i =>
    {
      var tt = Sites.oneNews(cat, sites[i]);
      results.Add(tt.Result);
    });
  });

  results.CompleteAdding(); // notify any enumerable that no more items will arrive
}

void Consumer()
{
  foreach (var result in results.GetConsumingEnumerable())
  {
    // each result will arrive here as soon as it becomes available
  }
}

只需将
results
制作成线程安全的生产者-消费者集合即可。它有
getconsumineGenumerable
方法,该方法返回一个IEnumerable,该IEnumerable将在另一个代码部分将项添加到集合中时立即生成该项

var results = new BlockingCollection<Result>();

async Task ProducerAsync()
{
  await Task.Run(() => // I removed the async here as it was not needed
  {
    Parallel.For(0, k, i =>
    {
      var tt = Sites.oneNews(cat, sites[i]);
      results.Add(tt.Result);
    });
  });

  results.CompleteAdding(); // notify any enumerable that no more items will arrive
}

void Consumer()
{
  foreach (var result in results.GetConsumingEnumerable())
  {
    // each result will arrive here as soon as it becomes available
  }
}

也许我有点误解,但是有什么能阻止你从并行调用一个方法来处理结果呢?代码如下。我们已经在不同的线程上,所以处理一组结果不会阻止处理下一组结果,这就是@ckuri的consumerfor循环中发生的事情,该循环处理同一线程上的所有结果。当然,这只有在处理速度缓慢时才重要

这看起来很琐碎,我想知道我是否误解了实际问题

await Task.Run(() =>
{
    Parallel.For(0, k, i =>
    {
        var tt = Sites.oneNews(cat, sites[i]);
        var result = tt.Result;
        results.Add(result);
        // Call a method to handle the results as they arise
        HandleResult(result);
    });
});

也许我有点误解,但是有什么能阻止你从并行调用一个方法来处理结果呢?代码如下。我们已经在不同的线程上,所以处理一组结果不会阻止处理下一组结果,这就是@ckuri的consumerfor循环中发生的事情,该循环处理同一线程上的所有结果。当然,这只有在处理速度缓慢时才重要

这看起来很琐碎,我想知道我是否误解了实际问题

await Task.Run(() =>
{
    Parallel.For(0, k, i =>
    {
        var tt = Sites.oneNews(cat, sites[i]);
        var result = tt.Result;
        results.Add(result);
        // Call a method to handle the results as they arise
        HandleResult(result);
    });
});

ObservableCollection不是线程安全的,因此尝试从多个线程添加到它(如此处完成)将导致错误。ObservableCollection不是线程安全的,因此尝试从多个线程添加到它(如此处完成)将导致错误。我需要在任何地方引用使用者方法吗?我在代码中实现了这一点,但是Consumer方法中的代码从未执行过。是的,您会执行,因为框架如何知道它应该调用它。这更多的是作为一个单独的生产者和消费者部分的例子。我修改了我的答案,如果你将生产者和消费者合并到一个方法中,会是什么样子。我需要在任何地方引用消费者方法吗?我在代码中实现了这一点,但是Consumer方法中的代码从未执行过。是的,您会执行,因为框架如何知道它应该调用它。这更多的是作为一个单独的生产者和消费者部分的例子。我修改了我的答案,如果你将生产者和消费者合并到一个方法中,会是什么样子。我先尝试了这个方法,但出现了一个例外。无法在CollectionChanged事件期间更改ObservableCollection我首先尝试了此操作,但引发了异常。无法在CollectionChanged事件期间更改ObservableCollection