public override UITableViewCell GetCell(UITableView tableView, Foundation.NSIndexPath indexPath) { // We will need a cancellationTokenSource so we can cancel the async call if the view moves back on screen // while text is already being loaded. Without this, if a view is loading some text, but the view moves off // and back on screen, the new load may take less time than the old load and then the old load will // overwrite the new text load and the wrong data will be displayed. So we will c ancel any async task on a // recycled view before loading the new text. CancellationTokenSource cts; TableViewCellWithCTS cell = tableView.DequeueReusableCell(CellIdentifier) as TableViewCellWithCTS; if (cell == null) { cell = new TableViewCellWithCTS(UITableViewCellStyle.Default, CellIdentifier); } else { // If cell exists, cancel any pending async text loading for this cell // by calling cts.Cancel(); cts = cell.Cts; // If cancellation has not already been requested, cancel the async task if (!cts.IsCancellationRequested) { cts.Cancel(); } } cell.TextLabel.Text = "Placeholder"; // Create new CancellationTokenSource for this view's async call cts = new CancellationTokenSource(); // Add to the Cts property of the cell cell.Cts = cts; // Get the cancellation token to pass into the async method var ct = cts.Token; Task.Run(async() => { try { string text = await GetTextAsync(indexPath.Row, ct); InvokeOnMainThread(() => { cell.TextLabel.Text = text; }); } catch (System.OperationCanceledException ex) { Console.WriteLine($"Text load cancelled: {ex.Message}"); } catch (Exception ex) { Console.WriteLine(ex.Message); } }, ct); return(cell); }
public override UITableViewCell GetCell(UITableView tableView, Foundation.NSIndexPath indexPath) { TableViewCellWithCTS cell = tableView.DequeueReusableCell(CellIdentifier) as TableViewCellWithCTS; if (cell == null) { cell = new TableViewCellWithCTS(UITableViewCellStyle.Default, CellIdentifier); } string text = GetTextAsync(indexPath.Row).Result; cell.TextLabel.Text = text; return(cell); }