10 Stimmen

SqlDataAdapter.Fill - Asynchroner Ansatz

Mit C# / .NET 3.5.

Derzeit fülle ich 2 DataTables eine nach der anderen mit SqlDataAdapter.Fill().

Ich möchte diese beiden Datentabellen parallel und gleichzeitig auffüllen, indem ich jede einzelne asynchron ausführe. Allerdings gibt es keine asynchrone Version der Fill()-Methode - d.h. BeginFill() wäre toll!

Ein Ansatz, den ich ausprobiert habe, ist (pseudo):

  1. SqlCommand1.BeginExecuteReader // 1. Abfrage, für DataTable1
  2. SqlCommand2.BeginExecuteReader // 2. Abfrage, für DataTable2
  3. SqlCommand1.EndExecuteReader
  4. SqlCommand2.EndExecuteReader
  5. DataTable1.Load(DataReader1)
  6. DataTable2.Load(DataReader2)

DataTable.Load() benötigt jedoch viel Zeit:
Die Ausführung der Schritte 1 bis 4 dauert 3 Sekunden.
Schritt 5 dauert dann 22 Sekunden.
Schritt 6 dauert 17 Sekunden.
Also, 39 Sekunden für die Schritte 5 und 6 zusammen.

Das Endergebnis ist, dies gibt mir keinen Vorteil über gerade tun 2 SqlDataAdapter.Fills, eine nach der anderen. Ich möchte das Nettoergebnis zu sein, dass der gesamte Prozess nur so lange wie die längste Abfrage (oder so nah wie möglich) dauert.

Auf der Suche nach empfohlenen Wege nach vorn, um am Ende mit etwas, das wirklich eine asynchrone Ansatz zum Füllen einer DataTable ist.

Oder muss ich nur verwalten es selbst und rollen 2 separate Threads, jeder eine DataTable füllen?

5voto

James Punkte 77534

Ich würde vorschlagen, einen separaten Worker-Thread für jeden zu haben. Sie könnten verwenden ThreadPool.QueueUserWorkItem .

List<AutoResetEvent> events = new List<AutoResetEvent>();

AutoResetEvent loadTable1 = new AutoResetEvent(false);
events.Add(loadTable1);
ThreadPool.QueueUserWorkItem(delegate 
{ 
     SqlCommand1.BeginExecuteReader;
     SqlCommand1.EndExecuteReader;
     DataTable1.Load(DataReader1);
     loadTable1.Set();
});

AutoResetEvent loadTable2 = new AutoResetEvent(false);
events.Add(loadTable2);
ThreadPool.QueueUserWorkItem(delegate 
{ 
     SqlCommand2.BeginExecuteReader;
     SqlCommand2.EndExecuteReader;
     DataTable2.Load(DataReader2);
     loadTable2.Set();
});

// wait until both tables have loaded.
WaitHandle.WaitAll(events.ToArray());

1voto

Neil Barnwell Punkte 39692

Dies liegt daran, dass die DataTable hat eine Menge von Objekten zu erstellen (Zeilen, Werte). Sie sollten die Ausführung des Adapters und die Population einer Datentabelle in einem anderen Thread ausführen und synchronisieren, indem Sie warten, bis jeder Vorgang beendet ist, bevor Sie fortfahren.

Der folgende Code wurde in Notepad geschrieben und lässt sich wahrscheinlich nicht einmal kompilieren, aber ich hoffe, Sie verstehen die Idee...

// Setup state as a parameter object containing a table and adapter to use to populate that table here

void DoWork()
{
    List<AutoResetEvent> signals = GetNumberOfWaitHandles(2);

    var params1 = new DataWorkerParameters
        {
            Command = GetCommand1();
            Table = new DataTable();
        }

    var params2 = new DataWorkerParameters
        {
            Command = GetCommand2();
            Table = new DataTable();
        }

    ThreadPool.QueueUserWorkItem(state => 
        {
            var input = (DataWorkerParameters)state;
            PopulateTable(input);
            input.AutoResetEvent.Set(); // You can use AutoResetEvent.WaitAll() in the caller to wait for all threads to complete
        },
        params1
    );

    ThreadPool.QueueUserWorkItem(state => 
        {
            var input = (DataWorkerParameters)state;
            PopulateTable(input);
            input.AutoResetEvent.Set(); // You can use AutoResetEvent.WaitAll() in the caller to wait for all threads to complete
        },
        params2
    );

    WaitHandle.WaitAll(signals.ToArray());
}

void PopulateTable(DataWorkerParameters parameters)
{
    input.Command.ExecuteReader();
    input.Table.Load(input.Command);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X