当前位置:  开发笔记 > 编程语言 > 正文

parallel linq:AsParallel().forAll()使一些对象为空

如何解决《parallellinq:AsParallel().forAll()使一些对象为空》经验,为你挑选了2个好方法。

所以,我有一个非常奇怪的情况,似乎forAll()plinq查询删除了我的一些自定义对象,说实话,我不知道为什么.

var myArticles = data.FilterCustomerArticles([]params]).ToList(); //always returns 201 articles

result.Articles = new List();

try
{
    myArticles.AsParallel().ForAll(article =>
                    {
                        result.Articles.Add(new ArticleMinimal()
                        {
                            ArticleNumber = article.ArticleNumber,
                            Description = article.Description,
                            IsMaterial = false,
                            Price = article.PortionPrice.HasValue ? article.PortionPrice.Value : decimal.Zero,
                            Quantity = 1,
                            ValidFrom = new DateTime(1900, 1, 1),
                            ValidTo = new DateTime(2222, 1, 1)
                        });
                    });

}
catch (Exception ex)
{
    ...
}

几乎每次调用时,上面的代码都会返回不同的结果计数.它应该返回201 ArticleMinimal-Objects.相反,它会返回200,189,19x ......但不时会返回201.没有异常,没有.它只返回少于它应该的对象.

代码更改为"好醇'"优雅的foreach循环之后,我总是得到预期的201个对象.

工作守则:

var myArticles = data.FilterCustomerArticles([]params]).ToList(); //always returns 201 articles

result.Articles = new List();

try
{
    foreach (var article in myArticles) { 
        result.Articles.Add(new ArticleMinimal()
                        {
                            ArticleNumber = article.ArticleNumber,
                            Description = article.Description,
                            IsMaterial = false,
                            Price = article.PortionPrice.HasValue ? article.PortionPrice.Value : decimal.Zero,
                            Quantity = 1,
                            ValidFrom = new DateTime(1900, 1, 1),
                            ValidTo = new DateTime(2222, 1, 1)
                        });
    }

}
catch (Exception ex)
{
    ...
}

此外,在更多代码行之后,我还有另外一个代码forAll:

try
{
    result.Articles.AsParallel().ForAll(article =>
                {
                    if (article.Weight != null){
                        ...
                    }
                });
}
catch (Exception)
{
    ...
}

使用第一个forAll,这会抛出一个NullReferenceException- imho,因为它需要一些201个对象,但是一些Listentries是null.

现在我的实际问题是:为什么第一个forAll返回的对象少于应该的数量?!我能想到的唯一线索是内联声明new ArticleMinimal(){ ...});- 但即使这是因为它对我来说似乎很奇怪.使用plinq时是不是可以这样做?我只是在这里猜测.

希望你能帮忙.

最好的问候,Dom



1> angry person..:

您无法操纵result.Articles许多线程,因为这可能会破坏内部,正如您所观察到的那样.

而是将并行工作流转换为返回创建对象的管道:

result.Articles.AddRange(myArticles.AsParallel().Select(article =>
    new ArticleMinimal()
    {
        ArticleNumber = article.ArticleNumber,
        Description = article.Description,
        IsMaterial = false,
        Price = article.PortionPrice.HasValue ? article.PortionPrice.Value : decimal.Zero,
        Quantity = 1,
        ValidFrom = new DateTime(1900, 1, 1),
        ValidTo = new DateTime(2222, 1, 1)
    })
);

.Select这里,因为它正在ParallelQuery返回时执行.AsParallel()将在项目上并行运行.

.AddRange但是会要求ParallelQuery.GetEnumerator()将返回收集到一个长期收集的物品,给你想要的东西.

根本区别在于,.AddRange()在所有并行任务开始完成之前,可能不会添加任何内容,而如果添加适当的锁定,则会在生成时将项添加到集合中.但是,除非您想要观察在生产过程中流入集合的物品,否则在您的情况下这不太重要.



2> Jürgen Stein..:

List.Add不是线程安全的.请参阅/sf/ask/17360801/

使用任一锁

lock (result.Articles)
{
    result.Articles.Add(...);
}

或线程安全集合.我会使用临时收藏品并在最后使用result.Articles.AddRange(...)

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有