Reputation: 143
I have a list of objects, and I need to get one object in that list that best identifies a particular item and add that item in that object.
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;
}
}
}
The problem happens when GetRelatedCategoriesAsync
returns more than 100 records and the process would take too long, I am having troubles doing it asynchronously so what I did temporarily is that I 'uncategorize' the item if the related categories would reach at least 21 objects.
How do I make this asynchronous, I have also read about SemaphoreSlim but I am not sure if that is what I need to be using.
UPDATE After trying out Yuval Itzchakov suggestion, I am getting the following error:
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
Upvotes: 1
Views: 321
Reputation: 149518
I'm not sure that I understand the exact requirements from you algorithm, but it looks like you're trying to find the maximum out of all categories.
What you can do is define a class which implements IComparable<T>
and use PLINQ (Parallel LINQ) by calling AsParallel
and use its extension method ParallelEnumerable.Max
. It would look similar to this:
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;
}
}
And then you'd call your method like this:
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;
}
Upvotes: 1