Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Linq调用任务。运行时访问错误的成员,延迟执行问题?_C#_Linq_Asynchronous_Lambda_Task - Fatal编程技术网

C# Linq调用任务。运行时访问错误的成员,延迟执行问题?

C# Linq调用任务。运行时访问错误的成员,延迟执行问题?,c#,linq,asynchronous,lambda,task,C#,Linq,Asynchronous,Lambda,Task,对于使用错误值的linq查询,我遇到了一个奇怪的问题。我的代码如下所示 await Task.WhenAll((from item in itemsToProcess let taskCount = count++ select Task.Run(() => { process(item).Result; })) .AsParallel().ToArray()); 基本上,我有一个50k项的列表,这些项被调用到一个进行web调用的方法中。它们完全不相关,可以以任何

对于使用错误值的linq查询,我遇到了一个奇怪的问题。我的代码如下所示

await Task.WhenAll((from item in itemsToProcess
    let taskCount = count++
    select Task.Run(() => { process(item).Result; }))
    .AsParallel().ToArray());
基本上,我有一个50k项的列表,这些项被调用到一个进行web调用的方法中。它们完全不相关,可以以任何顺序运行,并且不访问任何共享的内容。但是,有时,它会非常随机地将错误的项传递给process方法,就像在foreach循环中,如果不将其复制到局部变量,会遇到的情况一样

如果我把代码改成这个

await Task.WhenAll((from item in itemsToProcess
    let taskCount = count++
    let itemCopy = item
    select Task.Run(() => { process(itemCopy).Result; }))
    .AsParallel().ToArray());
那么我似乎没有这个问题。所以我的问题是,我是否遗漏了什么,或者这是预期的行为?我以为linq的from子句应该复制到本地副本,但事实不是这样吗?我很难找到任何能直接解决这个问题的方法。但是我看到了很多在linq表达式中调用异步方法而不执行额外let的示例


我也尝试过使lambda异步并等待该方法,但随后遇到了无线程的情况。也许有更好的方法?我很高兴知道这件事。简而言之,我所做的就是迭代一个列表并并行调用一个方法,因为它是I/O绑定的,而不是cpu绑定的。另一种可能是已经有很多关于这个的帖子了,我只是在寻找错误的术语。如果是这样的话,我也很高兴知道这一点。

并行和异步代码很少应该一起使用。理想情况下,并行仅适用于CPU限制的代码

为什么你不能这样做:

await Task.WhenAll(itemsToProcess.Select(item => process(item)));
根据评论进行编辑

通过使用
信号量lim
,可以(在某种程度上)轻松完成异步节流:

static SemaphoreSlim throttle = new SemaphoreSlim(50);
static async Task ProcessAsync(Item item)
{
  await throttle.WaitAsync();
  try
  {
    ... // Original process(item) code
  }
  finally
  {
    throttle.Release();
  }
}
这将限制项目处理到50。这只是我从空气中提取的一个数字;你应该尝试一下,找到一个合适的值


请注意,一旦工作变为异步,并行处理节流就停止工作。异步工作不会“占用”线程,因此它不计入并行处理限制(或线程池注入速率限制)。

这是一个很好的问题,我想知道如何摆脱并行调用。这个项目一开始是完全并行的,我决定异步重做,但我对异步非常陌生,所以我遇到了一些问题。当我这样做的时候,它实际上是在同一时间并行地运行每个调用,这会导致我的web调用超时,因为一次只能执行多个调用。使用任务池,它将任务限制为一次运行一定数量的任务,并将它们集中起来。如果有一种方法可以使用纯异步调用并将它们合并在一起,我认为这将是理想的。你的评论让这个出现在相关链接上,看起来像我可能需要的,谢谢!这似乎做得很好!你帮了大忙。我现在有很多测试要做,但这似乎工作得很好,在没有任务和跳过迭代的情况下,开销小得多。