public async Task IdentifyFacesAsync()
        {
            this.IdentifiedPersons = Enumerable.Empty <IdentifiedPerson>();

            Guid[] detectedFaceIds = this.DetectedFaces?.Select(f => f.FaceId).ToArray();
            if (detectedFaceIds != null && detectedFaceIds.Any())
            {
                List <IdentifiedPerson> result = new List <IdentifiedPerson>();

                IEnumerable <PersonGroup> personGroups = Enumerable.Empty <PersonGroup>();
                try
                {
                    personGroups = await FaceServiceHelper.GetPersonGroupsAsync(PeopleGroupsUserDataFilter);
                }
                catch (Exception e)
                {
                    ErrorTrackingHelper.TrackException(e, "Face API GetPersonGroupsAsync error");

                    if (this.ShowDialogOnFaceApiErrors)
                    {
                        await ErrorTrackingHelper.GenericApiCallExceptionHandler(e, "Failure getting PersonGroups");
                    }
                }

                foreach (var group in personGroups)
                {
                    try
                    {
                        IdentifyResult[] groupResults = await FaceServiceHelper.IdentifyAsync(group.PersonGroupId, detectedFaceIds);

                        foreach (var match in groupResults)
                        {
                            if (!match.Candidates.Any())
                            {
                                continue;
                            }

                            Person person = await FaceServiceHelper.GetPersonAsync(group.PersonGroupId, match.Candidates[0].PersonId);

                            IdentifiedPerson alreadyIdentifiedPerson = result.FirstOrDefault(p => p.Person.PersonId == match.Candidates[0].PersonId);
                            if (alreadyIdentifiedPerson != null)
                            {
                                // We already tagged this person in another group. Replace the existing one if this new one if the confidence is higher.
                                if (alreadyIdentifiedPerson.Confidence < match.Candidates[0].Confidence)
                                {
                                    alreadyIdentifiedPerson.Person     = person;
                                    alreadyIdentifiedPerson.Confidence = match.Candidates[0].Confidence;
                                    alreadyIdentifiedPerson.FaceId     = match.FaceId;
                                }
                            }
                            else
                            {
                                result.Add(new IdentifiedPerson {
                                    Person = person, Confidence = match.Candidates[0].Confidence, FaceId = match.FaceId
                                });
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        // Catch errors with individual groups so we can continue looping through all groups. Maybe an answer will come from
                        // another one.
                        ErrorTrackingHelper.TrackException(e, "Face API IdentifyAsync error");

                        if (this.ShowDialogOnFaceApiErrors)
                        {
                            await ErrorTrackingHelper.GenericApiCallExceptionHandler(e, "Failure identifying faces");
                        }
                    }
                }

                this.IdentifiedPersons = result;
            }

            this.OnFaceRecognitionCompleted();
        }
        public async Task IdentifyFacesAsync()
        {
            this.IdentifiedPersons = Enumerable.Empty <IdentifiedPerson>();

            Guid[] detectedFaceIds = this.DetectedFaces?.Where(f => f.FaceId.HasValue).Select(f => f.FaceId.GetValueOrDefault()).ToArray();
            if (detectedFaceIds != null && detectedFaceIds.Any())
            {
                List <IdentifiedPerson> result = new List <IdentifiedPerson>();

                var personGroupResultTasks             = new List <Tuple <string, Task <IList <IdentifyResult> > > >();
                IEnumerable <PersonGroup> personGroups = await GetPersonGroupsAsync();

                foreach (PersonGroup group in personGroups)
                {
                    personGroupResultTasks.Add(new Tuple <string, Task <IList <IdentifyResult> > >(group.PersonGroupId, GetFaceIdentificationResultsOrDefaultAsync(group.PersonGroupId, detectedFaceIds)));
                }

                // identify detected faces using person groups
                await Task.WhenAll(personGroupResultTasks.Select(x => x.Item2));

                // check matches
                foreach (var group in personGroupResultTasks)
                {
                    foreach (IdentifyResult match in group.Item2.Result)
                    {
                        if (!match.Candidates.Any())
                        {
                            continue;
                        }

                        Person person = null;
                        try
                        {
                            person = await FaceServiceHelper.GetPersonAsync(group.Item1, match.Candidates[0].PersonId);
                        }
                        catch { /* Ignore errors */ }

                        if (person == null)
                        {
                            continue;
                        }

                        IdentifiedPerson alreadyIdentifiedPerson = result.FirstOrDefault(p => p.Person.PersonId == match.Candidates[0].PersonId);
                        if (alreadyIdentifiedPerson != null)
                        {
                            // We already tagged this person in another group. Replace the existing one if this new one if the confidence is higher.
                            if (alreadyIdentifiedPerson.Confidence < match.Candidates[0].Confidence)
                            {
                                alreadyIdentifiedPerson.Person     = person;
                                alreadyIdentifiedPerson.Confidence = match.Candidates[0].Confidence;
                                alreadyIdentifiedPerson.FaceId     = match.FaceId;
                            }
                        }
                        else
                        {
                            result.Add(new IdentifiedPerson {
                                Person = person, Confidence = match.Candidates[0].Confidence, FaceId = match.FaceId
                            });
                        }
                    }
                }

                this.IdentifiedPersons = result;
            }
        }