Utilizzo delle attività sui controlli DataGrid

0

Recentemente, sto usando le attività sui controlli datagrid e nella mia applicazione ci sono quasi 20 datagrids in diverse forme.

Lo faccio perché a volte il recupero dei dati richiede molto tempo nel database e questo blocca la schermata dell'applicazione.

Ecco il mio bind di esempio:

string getAlert = "select * from testtable";

DataTable dtAlert = new DataTable();
OracleDataAdapter odaAlert = new OracleDataAdapter();

public void getAlertGrid()
{
    dtAlert.Clear();
    odaAlert = new OracleDataAdapter(getAlert, oradb);
    odaAlert.Fill(dtAlert);
    ugAlert.DataSource = dtAlert;
    ugAlert.DataBind();
}

Task.Factory.StartNew(() => GetAlertGrid());

Mi piacerebbe sapere cosa ne pensi? È sicuro o no?

    
posta S. Zunbag 27.01.2017 - 18:28
fonte

2 risposte

1

No, non è sicuro. Ci sono due problemi che mi vengono in mente immediatamente.

Accesso variabile non sincronizzato

dtAlert e odaAlert hanno un ambito tale che è possibile accedervi sia dal thread principale che dal thread di lavoro. Questo tipo di accesso ai dati deve essere sincronizzato .

Chiamare i controlli dell'interfaccia utente dal thread non dell'interfaccia utente

Tutti i controlli creati sul thread dell'interfaccia utente devono essere richiamati solo dal thread dell'interfaccia utente. Ciò include il tuo DataTable.

Per chiamare un controllo dell'interfaccia utente da un thread di lavoro, devi utilizzare Invoke . Ad esempio, per chiamare DataBind , si direbbe così:

dtaAlert.Invoke((MethodInvoker)delegate { dtaAlert.DataBind(); });
    
risposta data 01.02.2017 - 03:44
fonte
0

I do this because sometimes data retrieving takes a long time over database and that freezes the application screen.

È possibile separare i dati di caricamento e utilizzarli nell'interfaccia utente con metodi diversi, il che rende le responsabilità delle funzioni più chiare e non richiede il richiamo di controlli dell'interfaccia utente da altri thread.
Quindi non è necessario riutilizzare le stesse istanze di DataTable e DataAdapter .

public DataTable GetAlertData()
{
    var datatable = new DataTable();
    var query = "SELECT * FROM testtable";

    using (var connection = new OracleConnection(connectionString))
    using (var adapter = new OracleDataAdapter(query, connection))
    {
        var datatable = new DataTable();
        adapter.Fill(datatable);
    }

     return datatable;
}

Quindi avvolgi questo metodo con l'attività e "attendi" su di esso.

var data = await Task.Run(() => GetAlertData());
ugAlert.DataSource = data;

// ugAlert.DataBind();
// In Winforms you don't need to call DataBind - DataGridView does not have such a method.

Molto meglio sarà caricare i dati "completamente" in modo asincrono utilizzando metodi asincroni di connessione, comando e lettore di dati. Ma DataAdapter non supporta il metodo asincrono per Fill .

    
risposta data 21.10.2017 - 00:51
fonte

Leggi altre domande sui tag