0

I have a linq query like the following:

dim m As iEnumerable(Of DataRow)= (From b In tbl Select b).ToList.AsEnumerable

Where 'tbl' is a DataTable that has a huge number of rows and is updated all the time (Adding rows, removing rows, and modifying fields).

I've got an error of "Collection was modified" and couldn't run the part (.ToList)

The 'tbl' is always modified all the time and I don't want to stop the updates.

How can I retrieve an instance or at least How to access the query for reading only?

I want the query as the state when the query executed and I need it with no updates.

Any idea

  • Is the table being modified on other threads? – jmcilhinney Oct 08 '18 at 12:16
  • You "context" is not that clear; have you tried to create a copy of the `DataTable` with [DataTable.Copy](https://learn.microsoft.com/en-us/dotnet/api/system.data.datatable.copy?view=netframework-4.7.2), passing the current data to a new `DataTable`? – Jimi Oct 08 '18 at 13:11
  • 2
    There is never any reason to do `AsEnumerable` after `ToList`. – NetMage Oct 08 '18 at 20:10
  • It's been answered before: https://stackoverflow.com/a/21328343/832052. Very first sentence: `DataTable is simply not designed or intended for concurrent usage`. You will either need to choose a different data structure, or wrap the datatable to make it thread-safe. – djv Oct 08 '18 at 21:02
  • And your code can be simplified: `Dim m = tbl.AsEnumerable()` / `Dim m = tbl.AsEnumerable().ToList()` if you prefer to enumerate immediately. – djv Oct 08 '18 at 21:05
  • DataTable is not thread safe for write operations so not sure how you handle those. – Magnus Oct 09 '18 at 10:12

1 Answers1

0

I solved it as the following:

Because my DataTable is a multiThread DataTable, I wrote all editing code in BackgroundWorkers. So, All I did is to add one ManualResetEvent to my application and in all the procedures of all these BackgroundWorkers I added the following code just before the editing code:

ManualResetEvent.WaitOne()
... Editing DataTable here.

And When I need to get a copy of my DataTable I Do The following:

ManualResetEvent.Reset()
Thread.Sleep(300)

Then I accessed the dataTable freely and copied it to 'm' as I wanted.

dim m As iEnumerable(Of DataRow)= (From b In tbl Select b).ToList.AsEnumerable

After this I resumed the backgroundWorker by calling:

ManualResetEvent.Set()

I don't know if it is the best solution but at least it solved most of my issues.