Async Task button command firing multiple POSTs testing on Android hangs app?

I have a form that with a button command that can call a POST method 1 to x times depending on how many items in a Listview have been checked. I include the called button function and the actual method that is called. I'm not a async expert so my code was weaned from many articles I gleamed over. The POSTs acutually work, In my database I see the data posted (testing with two calls). So the code is kinda working but my android tablet hangs. So my question is if this is the right way to run multiple tasks in Xamarin Forms. I am testing on an Android right now but the App may go to production on either a Android or iPad so I'm looking for the best cross-platform best practices way of accomplishing. Using FreshMVVM.

Icommand def:
public ICommand CreatBomEvents { get; private set; }
bool bCanCreateEvents = true;

In constructor:
CreatBomEvents = new Command(async () => await cCreatBomEvents(), () => bCanCreateEvents);

ViewModel method:
async Task cCreatBomEvents()
{
CanCreateEvents(false);
try
{
var SelCnt = (from vba in BomAssemList where vba.Selected == true select vba).Count();
var vbaSel = (from vba in BomAssemList where vba.Selected == true select vba);
if (vbaSel.Any() )
{
Task[] taskArray = new Task[SelCnt];
int[] results = new int[SelCnt];
BomAssemEventAdd.BomAssemEventDate = DateTime.Now;
BomAssemEventAdd.LastUpdatedDate = DateTime.Now;
BomAssemEventAdd.LastUpdatedBy = currLogin.LoginName;
int forCnt = 0;
foreach (vBomAssemFabDet vba in vbaSel)
{
BomAssemEvent loopEvent = BomAssemEventAdd;
loopEvent.BomAssemID = vba.BomAssemID;
loopEvent.BomAssemRev = vba.BomAssemRev;
taskArray[forCnt] = _dataService.PostBomAssemEvent(loopEvent);
forCnt++;
}
Task.WaitAll(taskArray);
_EventAddResultMessage = "(" + forCnt.ToString() +")" + spBomAssemShipMark + "QA Done: " + BomAssemEventAdd.Notes ;
BomAssemEventAdd.Notes = string.Empty;
spBomAssemShipMark = string.Empty;
RaisePropertyChanged();
}
else
{ await CoreMethods.DisplayAlert("No Piecemarks Selected for QA Final!", "Error", "OK"); }
CanCreateEvents(true);
}
catch (Exception Ex)
{ _userDialogs.ShowError($"Error getting data: {Ex.Message}", 3000); }
finally
{ CanCreateEvents(true); }
}

Called dataservice method:
public async Task PostBomAssemEvent(BomAssemEvent pBomAssemEvent)
{
string RESTEntityURI = API_Base_URI + "BomAssemEvent";
var request = new HttpRequestMessage(HttpMethod.Post, RESTEntityURI);
var payload = JsonConvert.SerializeObject(pBomAssemEvent);
var mycontent = new StringContent(payload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _client.PostAsync(RESTEntityURI, mycontent);
var result = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
return result;
}

Answers

  • Not sure if this is the 'best practice' way for Xamarin.Forms or FreshMVVM but this change seemed to do the trick:

    In PageModel Constructor.

           CreateBomEvents = new Command(async () => await cCreatBomEvents().ConfigureAwait(continueOnCapturedContext: false), () => bCanCreateEvents);
    

    In the method call, the building of the tasks and then the final Task.WaitAll(taskArray); was left as is. All code needed to execute after the Tasks were finished was moved into the Finally{} of the Try. No more Hanging.

Sign In or Register to comment.