Here is my example of reading records from Database using Tasks in background, and Threads.
As
Jon Skeet wrote on
Stack Overflow:
A task returned by Task.Run() really is saying "I want you to execute this code separately"; the exact thread on which that code executes depends on a number of factors.
So, here is first my method with async. First install
Microsoft.Data.SqlClient here notice that old
System.Data.SqlClient is deprecated.
Now the method:
return Task.Run(() => ThreadReadFromDatabaseAsync(connectionString, sql));
private async Task ThreadReadFromDatabaseAsync(string connectionString, string sql)
{
DateTime start = DateTime.Now;
try
{
await using SqlConnection connection = new SqlConnection(connectionString);
await connection.OpenAsync();
await using SqlCommand command = new SqlCommand(sql, connection);
command.CommandTimeout = 3600;
await using SqlDataReader reader = await command.ExecuteReaderAsync();
int recdCnt = 0;
while (reader.Read())
{
UpdateUi.Execute($"{start} Reading using tasks record {recdCnt++}", LblRecordCount, Form);
object[] values = new object[reader.FieldCount];
reader.GetValues(values);
}
}
catch (Exception ex)
{
UpdateUi.Execute($"Error in task execution: {ex.Message}", LblError, Form);
}
finally
{
UpdateUi.Execute($"{DateTime.Now} Done with task execution", LblStatus, Form);
}
}
Here notice line:
while (reader.Read())
That I am not using
ReadAsync. The problem is that at ReadAsync will stuck on reading from DB after few hundert records, this looks like bug described
here.
Now another example with thread:
var thread = new Thread(() => ThreadReadFromDatabase(connectionString, sql))
{
Name = "ThreadReadFromDatabase",
IsBackground = true
};
thread.Start();
private void ThreadReadFromDatabase(string connectionString, string sql)
{
DateTime start = DateTime.Now;
try
{
using SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
using SqlCommand command = new SqlCommand(sql, connection);
command.CommandTimeout = 3600;
using SqlDataReader reader = command.ExecuteReader();
int recdCnt = 0;
while (reader.Read())
{
UpdateUi.Execute($"{start} Reading using threads record {recdCnt++}", LblRecordCount, Form);
object[] values = new object[reader.FieldCount];
reader.GetValues(values);
}
}
catch (Exception ex)
{
UpdateUi.Execute($"Error in thread execution: {ex.Message}", LblError, Form);
}
finally
{
UpdateUi.Execute($"{DateTime.Now} Done with thread execution", LblStatus, Form);
}
}
Full example download from
here
UPDATE 2025-03-12:
Avoid using Task.Run for long-running work that blocks the thread
Also from the book
Concurrency in C# Cookbook by Stephen Cleary:
As soon as you type new Thread(), it’s over; your project already has legacy code
Also check
this Stack Overflow answer.