I have 2 examples about mutating the data table inside of an async function. Since the DataTable and DataRow are of reference type, we can pass them into function and mutate - for example remove the row from the data table and this will effect the data table outside of the function. I know that doing so is unsafe in a multi threaded environment.
However this question pertains to the use of async await without making use of Task.Run - so effectively we always have 1 thread - the UI thread running the code.
Example 1-
private static async Task FuncAsync(DataTable dt, DataRow dr)
{
try
{
await Task.Delay(2000); //some io bound work here
Thread.Sleep(2000); //some syncronous blocking code here like log to db
dt.Rows.Remove(dr); //mutate datatable - remove the datarow from the datatable if there is no exception // this can be add/delete or even updating of the row
}
catch (Exception e)
{
Thread.Sleep(2000); //some syncronous blocking code here like log to db
}
}
private async void Button1_Click(object sender, EventArgs e)
{
List<Task> lstTasks = new List<Task>();
DataTable dt = (DataTable)gridview1.DataSource;
foreach (DataRow dr in dt.Rows)
{
lstTasks.Add(FuncAsync(dt, dr);
}
while (lstTasks.Any())
{
Task finishedTask = await Task.WhenAny(lstTasks);
lstTasks.Remove(finishedTask);
await finishedTask;
progressbar1.ReportProgress();
}
MessageBox.Show("Rows that resulted in exception: " + dt.Rows.Count.ToString());
}
}
Example 2-
private void Form1_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("col1");
for (int i =0; i < 1000; i++)
{
dt.Rows.Add(i);
}
dataGridView1.DataSource = dt; //Create datatable with 999 rows
}
private async Task FnMutateDtAsync(DataTable dt)
{
await Task.Delay(2000); //represents for io work
bool tst = false; //code following this line is syncronous
foreach (DataRow dr in dt.Rows)
{
if (dr["col1"].ToString() == "2") //if 2 exists then delete the 1st row
{
tst = true;
}
}
if (tst)
{
dt.Rows.RemoveAt(0); //mutate the datatable - this can be add/delete/modify value of cell
}
}
private async void button1_Click(object sender, EventArgs e)
{
List<Task> tsks = new List<Task>();
for (int i = 0; i < 5; i++) //run 5 tasks async
{
tsks.Add(FnMutateDtAsync((DataTable)dataGridView1.DataSource));
}
while (tsks.Any())
{
Task finishedTask = await Task.WhenAny(tsks);
tsks.Remove(finishedTask);
await finishedTask;
progressbar1.ReportProgress()
}
}
In both above examples, I am mutating the datatable from inside the async function.
Is there any harm that I must expect when writing code like this? Can I consider this coding style to be thread safe since at any point only 1 thread is doing all the work?
Is it safe to do ConfigureAwait(false) on the await line?