admin管理员组

文章数量:1122846

I could really use some help here, currently i'm developing a blazor server-side rendered application. Something is happening that with my current knowledge i cannot understand, maybe someone can help me out with this.

Currently i'm working on a page that contains roughly 2 elements, a user selection window and a scheduler that displays events for selected users. The code is still a bit messy, but the whole page works like intended, but there is a problem i can't explain.

After a change in the user selection window the data in the scheduler has to be refreshed because maybe some new events need to be added or deleted. This work but for some reason this is executed twice upon a certain line of code.

The method (async Task) for refreshing the data looks like this:

async Task LoadDataForScheduler(SchedulerLoadDataEventArgs args)
{
     List<User> selectedUsers = new List<User>();
     bool reload = false;

     //If no user is selected, the scheduler can be emptied
     if (tree.CheckedValues == null || tree.CheckedValues.Count() == 0)
     {
         appointments.Clear();
         return;
     }

     //Create list of selected users in the UI
     foreach (var checkedValue in tree.CheckedValues)
     {
         if (checkedValue is GroupMember groupMember)
         {
             selectedUsers.Add(groupMember.User);
         }
     }

     if (selectedUsers.Count == 0)
     {
         return;
     }

     List<int> selectedUserIds = selectedUsers.Select(x => x.Id).ToList();
     List<int> userIdsInCalender = appointments.Select(x => x.UserId.Value).ToList();
     userIdsInCalender = userIdsInCalender.Distinct().ToList();

     //This is for removing events from the scheduler for users that are no longer selected.
     if (userIdsInCalender.Count > 0)
     {
         foreach (int userId in userIdsInCalender)
         {
             if (!selectedUserIds.Contains(userId))
             {
                 appointments.RemoveAll(x => x.UserId == userId);
                 await scheduler.Reload();
             }
         }
     }

     List<Appointment> allAppointments = await _projectService.GetAppointmentsForUsersForPeriod(selectedUserIds, args.Start, args.End);
     List<Appointment> appointmentsToAdd = new List<Appointment>();

     foreach (int selectedUserId in selectedUserIds)
     {
         List<Appointment> userAppointments = allAppointments.Where(x => x.UserId == selectedUserId).ToList();
         appointmentsToAdd.AddRange(userAppointments);


         User selectedUser = await _userService.GetUserById(selectedUserId);
         string userEmail = selectedUser.Email;

         List<Appointment> outlookAppointments = await _graphController.GetAllEventsForUser(userEmail, args.Start, args.End);

         if (outlookAppointments != null && outlookAppointments.Count > 0)
         {
             appointmentsToAdd.AddRange(outlookAppointments);
         }
     }


     if (appointmentsToAdd != null && appointmentsToAdd.Count > 0)
     {
         foreach (var appointmentToAdd in appointmentsToAdd)
         {
             //Outlook appointments do not have an id yet, just add all received, duplicates might occur, fix this later
             if (appointmentToAdd.Id == 0)
             {
                 //HACK / TODO: fix later, add one hour to start and end
                 DateTime newStart = appointmentToAdd.StartDate.AddHours(1);
                 DateTime newEnd = appointmentToAdd.EndDate.AddHours(1);

                 appointmentToAdd.StartDate = newStart;
                 appointmentToAdd.EndDate = newEnd;

                 appointments.Add(appointmentToAdd);
                 reload = true;
                 continue;
             }

             //application appointments have an id, add only appointments that are not yet in the list to be rendered.
             if (!appointments.Any(x=>x.Id==appointmentToAdd.Id))
             {
                 appointments.Add(appointmentToAdd);
                 reload = true;
             }
         }
     }

     if (reload)
     {
         scheduler.Reload();
     }
 }

After debugging, it turns out that on the following line, 'LoadDataForScheduler' is executed again after this line:

List<Appointment> outlookAppointments = await _graphController.GetAllEventsForUser(userEmail, args.Start, args.End);

This is the async Task itself:

 public async Task <List<Appointment>> GetAllEventsForUser(string email, 
      DateTime periodStart, DateTime periodEnd)
 {
     try
     {
         List<Appointment> eventList = new List<Appointment>();
         string start = periodStart.ToString("s") + "Z";
         string end = periodEnd.ToString("s") + "Z";
         string filter = "start/dateTime ge " + "'" + start + "'" + " and end/dateTime le " + "'" + end + "'";

          
           var response = await_graphServiceClient.Users[email].Events.GetAsync((requestConfiguration) =>
         {

        requestConfiguration.QueryParameters.Expand = new string[] { "singleValueExtendedProperties($filter=id eq 'String {XXXXXXXXXXX} Name customid')" };
        requestConfiguration.QueryParameters.Filter = filter;
        requestConfiguration.QueryParameters.Top = 99;
        requestConfiguration.Options.WithAppOnly();
        requestConfiguration.Options.ToDynamicList();
    });

    if (response.Value.Count == 0)
    {
        return null;
    }

    foreach (var item in response.Value)
    {
        if (item.SingleValueExtendedProperties != null)
        {
            continue;
        }

        DateTime itemStart = item.Start.ToDateTime();
        DateTime itemEnd = item.End.ToDateTime();

        if (itemEnd - itemStart < TimeSpan.FromHours(1))
        {
            continue;
        }

        Appointment appointment = new Appointment();
        appointment.Subject = item.Subject;
        appointment.StartDate = item.Start.ToDateTime();
        appointment.EndDate = item.End.ToDateTime();

        eventList.Add(appointment);
    }

    return eventList;
}
catch (Exception ex)
{

    throw;
}

}

So in short, while executing async Task 'LoadDataForScheduler', another async Task is called named GetAllEventsForUsers, within this Task the following section makes it re-run the parent Task:

            var response = await _graphServiceClient.Users[email].Events.GetAsync((requestConfiguration) =>
            {

                requestConfiguration.QueryParameters.Expand = new string[] { "singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name proplanid')" };
                requestConfiguration.QueryParameters.Filter = filter;
                requestConfiguration.QueryParameters.Top = 99;
                requestConfiguration.Options.WithAppOnly();
                requestConfiguration.Options.ToDynamicList();
            });

I had the same issue with other async Task calls inside 'LoadDataForScheduler' but I could fix them by changing the EF Core calls (leave out the await and use ToList instead ToListAsync). And I really think this is the problem but I can't seems to figure how to fix this or why it's happing.

Any help is highly appreciated,

本文标签: cawaitable Task executed inside async Task makes it reinstantiateStack Overflow