我有一个简单的单元测试:
[TestMethod]
public void TestInitDatabases()
{
Debug.WriteLine("Testing loading up all databases!");
Assert.IsTrue(Library.InitDatabase());
}
ClassLibrary 中的一个方法尝试加载具有 58,139 条记录的实体。
public static bool InitDatabase()
{
Debug.WriteLine("Loading Entities");
var startTime = DateTime.Now;
DContext.Database.CommandTimeout = 180;
DContext.Database.Log = Console.WriteLine;
Task task = new Task(async () => await DContext.SA_HistoryHeader.LoadAsync());
Debug.WriteLine("All Tasks Assigned");
task.Start();
task.Wait();
while (!DContext.SA_HistoryHeader.Local.Any())
{
Debug.WriteLine("Task Status " + task.Status);
}
try
{
Debug.WriteLine("We are about to count the records...");
while (DContext.SA_HistoryHeader.Local.Count != 58139)
{
Debug.WriteLine("OrderHistory has " + DContext.SA_HistoryHeader.Local.Count + " Records");
}
}
catch (Exception ex)
{
Debug.WriteLine("Count Error: " + ex.Message);
return false;
}
Debug.WriteLine("Total Load Time: " + (DateTime.Now – startTime));
return true;
}
但是 try/catch 返回:
Count Error: Collection was modified; enumeration operation may not execute.
每次运行测试时。
输出显示:
...
OrderHistory has 1 Records
OrderHistory has 1 Records
OrderHistory has 1 Records
OrderHistory has 1 Records
OrderHistory has 1 Records
OrderHistory has 1 Records
OrderHistory has 1 Records
OrderHistory has 1 Records
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
Count Error: Collection was modified; enumeration operation may not execute.
A first chance exception of type 'Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException' occurred in Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
A first chance exception of type 'Microsoft.VisualStudio.TestTools.TestTypes.Unit.TestFailedException' occurred in Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll
The thread 'Agent: adapter run thread for test 'TestInitDatabases' with id '97fef094-3e43-4bfa-bb1d-02b70eb4b6f7'' (0x19ac) has exited with code 0 (0x0).
The thread 'Agent: test queue thread' (0x3a0) has exited with code 0 (0x0).
The thread 'Agent: state execution thread for test 'TestInitDatabases' with id '97fef094-3e43-4bfa-bb1d-02b70eb4b6f7'' (0x138c) has exited with code 0 (0x0).
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
...
偶尔,我会得到:
...
OrderHistory has 1 Records
OrderHistory has 1 Records
OrderHistory has 513 Records
然后同样的错误。我正在尝试找到加载实体表的最快方法。
编辑:我根据 Yuval Itzchakov 的评论更改了我的方法:
public static async void InitDatabase()
{
Debug.WriteLine("Loading Entities");
var startTime = DateTime.Now;
DateTime newTime;
DContext.Database.CommandTimeout = 180;
DContext.Database.Log = Console.WriteLine;
try
{
await DContext.SA_HistoryHeader.LoadAsync();
//DContext.SA_HistoryHeader.Load();
Debug.WriteLine("Orders has " + DContext.SA_HistoryHeader.Local.Count + " records");
Debug.WriteLine("OrderHistory Loaded: " + (DateTime.Now - startTime));
newTime = DateTime.Now;
await DContext.SA_HistoryDetail.LoadAsync();
//DContext.SA_HistoryDetail.Load();
Debug.WriteLine("Details has " + DContext.SA_HistoryDetail.Local.Count + " records");
Debug.WriteLine("OrderDetails Loaded: " + (DateTime.Now - newTime));
}
catch (SqlException ex)
{
foreach (SqlError error in ex.Errors)
Debug.WriteLine("Sql Exception Error: " + error.Message);
return;
}
catch (ThreadAbortException ex)
{
Debug.WriteLine("Thread - caught ThreadAbortException - resetting.");
Debug.WriteLine(string.Format("Exception message: {0}", ex.Message));
Thread.ResetAbort();
}
catch (Exception ex)
{
Debug.WriteLine("Load Exception Error: " + ex.Message);
return;
}
Debug.WriteLine("All Tasks Complete: " + (DateTime.Now - startTime));
return;
}
当我使用普通的旧加载时,订单实体将在大约 47 秒内加载。加载详细信息实体大约需要 19 分钟(358,501 条记录)。
当我将(注释/取消注释)更改为 LoadAsync 时,我得到的只是线程中止异常。
最佳答案
当前发生的情况是,您实际上正在等待 new Task
创建的外部任务,这意味着当您使用 Task.Wait
时,它将立即返回,而不是返回等待内部任务完成。
当您正在执行的操作是 IO 绑定(bind)时,我认为没有理由创建新任务
,您只需等待
操作即可:
await DContext.SA_HistoryHeader.LoadAsync()
这将保证操作在您查看 Count
属性之前完成数据收集。
关于c# - '集合已修改;使用 async/await 可能无法执行枚举操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26410192/