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# 列表中的线程不安全异步<>;。ForEach()_C#_Linq_Async Await - Fatal编程技术网

C# 列表中的线程不安全异步<>;。ForEach()

C# 列表中的线程不安全异步<>;。ForEach(),c#,linq,async-await,C#,Linq,Async Await,为什么在.ForEach()中执行等待是不安全的 在.NETCore3.1项目中,我从一些WebApi中选择符合条件的用户列表,然后删除它们,最后再次请求用户列表。当然,这次我希望列表是空的 错误的代码 var existing = (await client.GetByMatchAsync(new SearchParameters() {..})).ToList(); existing.ForEach(async x => await client.DeleteById

为什么在
.ForEach()中执行
等待
是不安全的

在.NETCore3.1项目中,我从一些WebApi中选择符合条件的用户列表,然后删除它们,最后再次请求用户列表。当然,这次我希望列表是空的

错误的代码

    var existing = (await client.GetByMatchAsync(new SearchParameters() {..})).ToList();

    existing.ForEach(async x => await client.DeleteByIdAsync(x.Id));

    var ensure = (await client.GetByMatchAsync(new SearchParameters() {..})).ToList();
    ensure.Count.Should().Be(0);  <-- ERROR WAS 1!
备选工作代码(使用foreach)

反编译
.ForEach()
我看不出线程问题发生在哪里

    public void ForEach(Action<T> action)
    {
        if (action == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
        }

        int version = _version;

        for (int i = 0; i < _size; i++)
        {
            if (version != _version)
            {
                break;
            }
            action!(_items[i]);
        }

        if (version != _version)
            ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
    }
public void ForEach(操作)
{
if(action==null)
{
ThrowHelper.ThrowArgumentNullException(argument.action除外);
}
int版本=_版本;
对于(int i=0;i<\u size;i++)
{
如果(版本!=\u版本)
{
打破
}
行动!(_项[i]);
}
如果(版本!=\u版本)
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}

列表的ForEach只执行一个
操作
,因此每次迭代都不会等待您提供的操作,在调用完成之前可以继续执行

否则,它可能会有一个带有签名的重载

Task ForEach(Func<T, Task> func)

.ForEach()只执行一个操作,而不是Func,因此您永远不会等待它。
existing.ForEach
启动一系列任务,而不是等待它们完成,因此它们都会同时运行
foreach{await}
在开始下一个任务之前等待上一个任务。在foreach反编译中,action!(_项目[i]);感叹号是一个奇怪的语句吗?@CRice问ReSharper
是什么平均值;)这个问题被描述为#5,因为我不确定,我只想问:您仍然对
async(value)感到困惑吗=>等待任务。CompletedTask
可以同时分配给
Fun
Action
?@Ackdari我知道它可以这样,但如果在不同的时间进行,则不能将一个实例分配给另一个实例-没有隐式转换。
    public void ForEach(Action<T> action)
    {
        if (action == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
        }

        int version = _version;

        for (int i = 0; i < _size; i++)
        {
            if (version != _version)
            {
                break;
            }
            action!(_items[i]);
        }

        if (version != _version)
            ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
    }
Task ForEach(Func<T, Task> func)
Action<string> a = async (value) => await Task.CompletedTask;
existing.ForEach(async x => await client.DeleteByIdAsync(x.Id));