У меня есть набор данных, который используется в разных потоках. Но каждый DataTable используется только в определенном потоке. Время от времени я получаю эту ошибку: Collection was modified; enumeration operation may not execute.
Вот мой код:
DataTable dt = null;
lock (ds)
{
dt = ds.Tables.Add("FeedbackSummary");
}
dt.Columns.Add("FeedbackId", typeof(int));
dt.Columns.Add("Question", typeof(string));
dt.Columns.Add("Total Ratings", typeof(int));
dt.Columns.Add("Total Votes", typeof(int));
List<Feedback> feedbacks = GetFeedbacks();
foreach (Feedback f in feedbacks)
{
int id = f.FeedbackId;
DataRow dr = dt.Select("FeedbackId=" + id).FirstOrDefault();
if (dr == null)
{
dr = dt.NewRow();
dr["FeedbackId"] = id;
dr["Question"] = f.Question;
dr["Total Ratings"] = 0;
dr["Total Votes"] = 0;
dt.Rows.Add(dr); //error occurs here. dt.Rows.Count is 0
}
dr["Total Votes"] = (int)dr["Total Votes"] + f.TotalVotes;
dr["Total Ratings"] = (int)dr["Total Ratings"] + f.TotalRating;
}
Это происходит на dt.Rows.Add
, даже если DataTable не является общим и нет foreach
выполняется в строках DataTable. Что еще хуже, это происходит периодически.
Полные ошибки (из StackTrace исключения):
at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
at System.Data.ConstraintEnumerator.GetNext()
at System.Data.DataTable.CascadeAll(DataRow row, DataRowAction action)
at System.Data.DataTable.RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction, Boolean fireEvent)
at System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean suppressEnsurePropertyChanged, Int32 position, Boolean fireEvent, Exception& deferredException)
at System.Data.DataTable.InsertRow(DataRow row, Int64 proposedID, Int32 pos, Boolean fireEvent)
at System.Data.DataRowCollection.Add(DataRow row)
at Website.GenerateFeedbackSummary(DataSet ds) in C:\Pro\Website\Website\Utils\Reports.Summary.cs:line 88
at Website.ReportUtils.<>c__DisplayClass80_0.<GenerateReportSummary>b__3() in C:\Pro\Website\Website\Utils\ReportUtil.cs:line 565
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
Есть идеи?
Спасибо ...
Вот код для GetFeedbacks ()
using (EFOrderDB ef = DBProvider.Create())
{
return DBProvider.GetRetryPolicy().ExecuteAction<List<Feedback>>(() =>
{
return (from rec in ef.Feedbacks.AsNoTracking()
select rec).Take(20).ToList<Feedback>();
});
}