5

I have a DataAdapter that is filling 5 DataTables in a DataSet.

SqlDataAdapter da = new SqlDataAdapter("Select * from testTable",con);
da.Fill(ds, 0, numberOfRowsToPutInEachDataTable, "DT1");
da.Fill(ds, numberOfRowsToPutInEachDataTable , numberOfRowsToPutInEachDataTable , "DT2");
da.Fill(ds, numberOfRowsToPutInEachDataTable* 2, numberOfRowsToPutInEachDataTable, "DT3");
da.Fill(ds, numberOfRowsToPutInEachDataTable * 3, numberOfRowsToPutInEachDataTable, "DT4");
da.Fill(ds, numberOfRowsToPutInEachDataTable * 4, numberOfRowsToPutInEachDataTable, "DT5");

My goal is to get each

da.Fill...

to run asynchronously, at the same time.

I have no experience running things asynchronously and am having a hard time finding the solution through research. Can anyone show me how I can get each of these DataAdapter.Fill() to run asynchronously?

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Reeggiie
  • 782
  • 7
  • 16
  • 36
  • rather than putting some rows here and other rows there, you can load them all and use a DataView to show them in pages of 500 or whatever - if that is the reason for chopping them up – Ňɏssa Pøngjǣrdenlarp Jul 20 '16 at 18:43
  • 3
    There are no asynchronous methods for `DataAdapter`. You'd be restricted to tasks although there are probably better ways to solve your problem. – David L Jul 20 '16 at 18:43
  • Getting them to run at the same time is my only requirement. – Reeggiie Jul 20 '16 at 18:45
  • @DavidL How could I achieve this using task? – Reeggiie Jul 20 '16 at 19:49
  • 1
    @Reeggiie I'd recommend creating 5 separate, paged queries and executing them in separate adapters personally, spun up in new tasks. Or even better, I'd get away from this type of thing altogether. – David L Jul 20 '16 at 19:52
  • There is currently an effort to implement async functionality to DataAdapter.Fill in .NET at https://github.com/dotnet/runtime/issues/22109 – Lachlan Ennis Jun 21 '20 at 22:56

2 Answers2

3

You can use multiple threads of multiple Task.Run() this way:

Task.Run(() =>
{
    da1.Fill(ds.Table1);
    this.Invoke(new Action(() => {dataGridView1.DataSource = ds.Table1;}));
});
Task.Run(() =>
{
    da2.Fill(ds.Table2);
    this.Invoke(new Action(() => {dataGridView2.DataSource = ds.Table2;}));
});

This way data will load using 2 different threads at the same time without freezing the form.

In above code, da1.Fill and da2.Fill will call in different threads at the same time. Since the code is executing a different thread than UI thread, to set the DataSource of DataGridView you should use Invoke.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
-1

How about using PLINQ:

SqlDataAdapter da = new SqlDataAdapter("Select * from testTable", con);

IEnumerable<int> results = new string[]
{
    "DT1", "DT2", "DT3", "DT4", "DT5"
}
.AsParallel()
.Select((table, index) => da.Fill(ds, 
                          numberOfRowsToPutInEachDataTable * index, 
                          numberOfRowsToPutInEachDataTable, 
                          table));

EDIT

The proposed solution is definitely not recommended.

It appears that DataSet does not support concurrent write operations:

This type is safe for multithreaded read operations. You must synchronize any write operations.

Community
  • 1
  • 1
Matias Cicero
  • 25,439
  • 13
  • 82
  • 154