Cómo cancelar una consulta asíncrona de la manera correcta.

.net c# entity-framework entity-framework-6 wpf

Pregunta

Esta es una pregunta de seguimiento a esta pregunta .

Estoy tratando de cargar datos de mi base de datos, lo cual tomará de 5 a 10 segundos, pero quiero que la GUI se mantenga receptiva y también debería poder cancelarse.

private CancellationTokenSource _source;

public IEnumerable<Measurement> Measurements { get { ... } set { ... } }

private async void LoadData()
{
    _source = new CancellationTokenSource();

    using (var context = new TraceContext())
    {
        Measurements = null;
        Measurements = await context.Measurements.ToListAsync(_source.Token);
    }
}

private void Cancel()
{
    if (_source != null)
        _source.Cancel();
}

public RelayCommand ReloadCommand
{
    get { return _reloadCommand ?? (_reloadCommand = new RelayCommand(Reload)); }
}
private RelayCommand _reloadCommand;

public RelayCommand CancelCommand
{
    get { return _cancelCommand ?? (_cancelCommand = new RelayCommand(Cancel)); }
}
private RelayCommand _cancelCommand;

He intentado algunas cosas, pero simplemente no puedo hacer que esto funcione correctamente, esto solo carga la Lista y eso es todo, no puedo cancelar esto.

¿Dónde está el error en esto?

Respuesta aceptada

Gracias por hablar de esto. Actualmente, la implementación de esta API asíncrona en EF se basa en el proveedor subyacente de ADO.NET para cumplir con la cancelación, pero SqlDataReader.ReadAsync tiene algunas limitaciones y hemos observado que en muchos casos no se cancelará inmediatamente cuando se solicite la cancelación. Tenemos un error que estamos considerando para corregir en EF6 RTM que trata de introducir nuestros propios cheques para las solicitudes de cancelación entre lecturas de fila dentro de los métodos EF.

Mientras tanto, puede solucionar esta limitación utilizando ForEachAsync () para agregar elementos a la lista y revisar cada fila, por ejemplo (no está probado a fondo):

    public async static Task<List<T>> MyToListAsync<T>(
        this IQueryable<T> source,
        CancellationToken token)
    {
        token.ThrowIfCancellationRequested();
        var list = new List<T>();
        await source.ForEachAsync(item =>
        {
            list.Add(item);
            token.ThrowIfCancellationRequested();
        });
        return list;
    }



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué