2
執行以下代碼時。使用異步和DataRow的非線程安全代碼
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
namespace AsyncDataRow
{
internal class Program
{
private static void Main(string[] args)
{
var program = new Program();
try
{
Console.WriteLine("Execute");
for (int i = 0; i < 100; i++)
{
program.Execute();
}
}
catch (AggregateException aggregateException)
{
foreach (var exception in aggregateException.InnerExceptions)
{
Console.WriteLine("AggregateException.InnerExceptions: " + exception.Message);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception.Message: " + ex.Message);
}
Console.ReadKey();
}
private void Execute()
{
DataTable dataTable = new DataTable();
dataTable.Columns.Add("ID", typeof(int));
dataTable.Columns.Add("Name", typeof(string));
for (int i = 0; i < 1000; i++)
{
dataTable.Rows.Add(i, i.ToString());
}
var taskList = new List<Task>();
foreach (DataRow dataRow in dataTable.Rows)
{
taskList.Add(ChangeStringValue(dataRow));
}
Task.WaitAll(taskList.ToArray());
}
private async Task ChangeStringValue(DataRow dataRow)
{
var id = (int)dataRow["ID"];
var newValue = await Task.Run(() => CreateNewValue(id));
dataRow["Name"] = newValue;
}
private string CreateNewValue(int id)
{
Console.WriteLine(string.Format("{0} - CreateNewValue", id));
return id.ToString() + "New StringValue";
}
}
}
間歇地System.ArgumentOutOfRangeException被扔在這行代碼
dataRow["Name"] = newValue
異常消息:
Exception thrown: 'System.ArgumentOutOfRangeException' in mscorlib.dll
Additional information: Index was out of range. Must be non-negative and less than the size of the collection.
我想更具體的識別問題,但最近我得到了簡化代碼來重現錯誤。
我認爲它與傳入異步方法的DataRow引用類型有關,但我想知道爲什麼這個代碼不是線程安全的。
正如您似乎已經發現的那樣,'DataRow'元素不能同時從多個線程發生變異。你不需要從多個線程操縱它們。 – Servy