异步处理对象列表

时间:2015-08-12 10:53:36

标签: c# asynchronous async-await

我有一个对象列表,我需要在该列表中获得一个最能识别特定项目的对象,并在该对象中添加该项目。

List<Category> endpoints = new List<Category>();
endpoints = await GetRelatedCategoriesAsync(pp);
float catScore = 0;
Category categoryHit = new Category();

// THIS LOOP SHOULD BE ASYNCHRONOUS
foreach (Category cat in endpoints)
{
    SentenceSimilarity similarity = new SentenceSimilarity();
    string phrase = cat.Keywords.Replace("|", " ");
    float score = similarity.GetScore(phrase, string.IsNullOrEmpty(wholeWord) ? "" : wholeWord);

    if (catScore == 0)
    {
       catScore = score;
       categoryHit = cat;
    }
    else
    {
        if (catScore > score)
        {
            // Do something here
        }
        else
        {
           catScore = score;
           categoryHit = cat;
        }
    }
}

问题发生在GetRelatedCategoriesAsync返回超过100条记录并且过程需要太长时间的时候,我遇到了异步操作问题所以我暂时做的就是如果相关类别会将项目分类为“未分类”达到至少21个物体。

我如何使这个异步,我也读过SemaphoreSlim,但我不确定这是否是我需要使用的。

更新 在尝试 Yuval Itzchakov 建议后,我收到以下错误:

at System.Linq.Parallel.QueryTaskGroupState.QueryEnd(Boolean userInitiatedDispose)
at System.Linq.Parallel.SpoolingTask.SpoolStopAndGo[TInputOutput,TIgnoreKey](QueryTaskGroupState groupState, PartitionedStream`2 partitions, SynchronousChannel`1[] channels, TaskScheduler taskScheduler)
at System.Linq.Parallel.DefaultMergeHelper`2.System.Linq.Parallel.IMergeHelper<TInputOutput>.Execute()
   at System.Linq.Parallel.MergeExecutor`1.Execute()
   at System.Linq.Parallel.MergeExecutor`1.Execute[TKey](PartitionedStream`2 partitions, Boolean ignoreOutput, ParallelMergeOptions options, TaskScheduler taskScheduler, Boolean isOrdered, CancellationState cancellationState, Int32 queryId)
   at System.Linq.Parallel.PartitionedStreamMerger`1.Receive[TKey](PartitionedStream`2 partitionedStream)
   at System.Linq.Parallel.AssociativeAggregationOperator`3.WrapPartitionedStream[TKey](PartitionedStream`2 inputStream, IPartitionedStreamRecipient`1 recipient, Boolean preferStriping, QuerySettings settings)
   at System.Linq.Parallel.UnaryQueryOperator`2.UnaryQueryOperatorResults.ChildResultsRecipient.Receive[TKey](PartitionedStream`2 inputStream)
   at System.Linq.Parallel.UnaryQueryOperator`2.UnaryQueryOperatorResults.GivePartitionedStream(IPartitionedStreamRecipient`1 recipient)
   at System.Linq.Parallel.UnaryQueryOperator`2.UnaryQueryOperatorResults.GivePartitionedStream(IPartitionedStreamRecipient`1 recipient)
   at System.Linq.Parallel.QueryOperator`1.GetOpenedEnumerator(Nullable`1 mergeOptions, Boolean suppressOrder, Boolean forEffect, QuerySettings querySettings)
   at System.Linq.Parallel.QueryOpeningEnumerator`1.OpenQuery()
   at System.Linq.Parallel.QueryOpeningEnumerator`1.MoveNext()
   at System.Linq.Parallel.AssociativeAggregationOperator`3.Aggregate()
   at System.Linq.AggregationMinMaxHelpers`1.Reduce(IEnumerable`1 source, Int32 sign)
   at System.Linq.AggregationMinMaxHelpers`1.ReduceMax(IEnumerable`1 source)
   at System.Linq.ParallelEnumerable.Max[TSource](ParallelQuery`1 source)
   at System.Linq.ParallelEnumerable.Max[TSource,TResult](ParallelQuery`1 source, Func`2 selector)
   at Scraper.UskoopScraper.<GetCategoryIdAsync>d__80.MoveNext() in d:\projects\\\file.cs:line 1001

1 个答案:

答案 0 :(得分:1)

我不确定我是否理解您算法的确切要求,但看起来您正试图找到所有类别中的最大值。

您可以做的是定义一个实现AsParallel的类,并通过调用ParallelEnumerable.Max并使用其扩展方法public class CategoryResult : IComparable<CategoryResult> { public Category Category { get; set; } public int Score { get; set; } public int CompareTo(CategoryResult other) { int comparison = 0; if (this.Score == other.Score) { comparison = 0; } else if (this.Score > other.Score) { comparison = 1; } else if (this.Score < other.Score) { comparison = -1; } return comparison; } } 来使用PLINQ(并行LINQ)。它看起来与此类似:

var maxCategoryResult = list.AsParallel().Max(cat => 
{
    SentenceSimilarity similarity = new SentenceSimilarity();
    string phrase = cat.Keywords.Replace("|", " ");
    float score = similarity.GetScore(
                phrase, string.IsNullOrEmpty(wholeWord) ? "" : wholeWord);

    CategoryResult catResult = null;
    if (catScore == 0 || catScore < score)
    {
        catResult = new CategoryResult
        {
            Category = cat,
            Score = score
        }
    }
    else
    {
        // Create different category?
    }

    return catResult;
}

然后你会像这样打电话给你的方法:

{{1}}