PC Review
Forums
Newsgroups
Microsoft DotNet
Microsoft ADO .NET
Data View Thread Safety Problem
Forums
Newsgroups
Microsoft DotNet
Microsoft ADO .NET
Data View Thread Safety Problem
![]() |
Data View Thread Safety Problem |
|
|
Thread Tools | Rate Thread |
|
|
#1 |
|
Guest
Posts: n/a
|
I have a multi-threaded application with a static constructor and static
DataSet and DataView variables, populated in the constructor. i then create many threads to access the static DataView but some of the threads generate errors while others work. Here is the code for the sample console app using System; using System.Data; using System.Threading; namespace DataViewTest { class DataViewTest { static DataSet _ds; static DataView _dv; private volatile Thread _thread; private string _name; static DataViewTest() { _ds = new DataSet(); DataTable tableOne = new DataTable("TableOne"); tableOne.Columns.Add(new DataColumn("Force", typeof (int))); tableOne.Columns.Add(new DataColumn("Section", typeof (string))); tableOne.Columns.Add(new DataColumn("ApplicationID", typeof (string))); tableOne.Columns.Add(new DataColumn("GroupID", typeof (int))); tableOne.Columns.Add(new DataColumn("Name", typeof (string))); DataRow newRow = tableOne.NewRow(); newRow["Force"] = 13; newRow["Section"] = "0"; newRow["ApplicationID"] = "FA"; newRow["GroupID"] = 1; newRow["Name"] = "ZZ"; tableOne.Rows.Add(newRow); _dv = new DataView(tableOne, null, "GroupID", DataViewRowState.CurrentRows); _ds.Tables.Add(tableOne); _ds.AcceptChanges(); } public DataViewTest(string threadName) { _name = threadName; } internal void Run() { if(_dv[0]==null) { System.Diagnostics.Trace.WriteLine(string.Format("{0} FAILED", _name)); } else System.Diagnostics.Trace.WriteLine(string.Format("{0} worked", _name)); } internal void Start() { _thread = new Thread(new ThreadStart(Run)); _thread.Name = _name; _thread.IsBackground = true; _thread.Start(); } } /// <summary> /// Summary description for Class1. /// </summary> class Class1 { private static DataViewTest[] _workers; /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { _workers = new DataViewTest[100]; for (int ct=0; ct<_workers.Length; ct++) { _workers[ct] = new DataViewTest(string.Format("Thread '{0}'", ct)); } for (int ct=0; ct<_workers.Length; ct++) { _workers[ct].Start(); } while(true) Thread.Sleep(1000); } } } here is some sample output Thread '0' worked The thread 'Thread '0'' (0x1dd4) has exited with code 0 (0x0). Thread '27' worked The thread 'Thread '27'' (0x1f18) has exited with code 0 (0x0). Thread '63' worked Thread '6' worked Thread '1' FAILED The thread 'Thread '6'' (0x1e70) has exited with code 0 (0x0). The thread 'Thread '1'' (0x1b08) has exited with code 0 (0x0). Thread '3' FAILED The thread 'Thread '3'' (0x14d8) has exited with code 0 (0x0). Thread '11' worked Thread '2' FAILED The thread 'Thread '11'' (0x1d90) has exited with code 0 (0x0). The thread 'Thread '2'' (0x1bd8) has exited with code 0 (0x0). Thread '5' worked The documentation says that DataViews are threadsafe, so why is this happening? Sometimes, everything is OK, but more often than not, at least one thread fails. |
|
|
|
#2 |
|
Guest
Posts: n/a
|
Shaeney,
I wont believe that the dataview (especially the 2005 version) will ever work in another thread than the datatable. The dataview is dynamic, so every change in the datatable (and visa versa) will afect it. Cor "Shaeney" <u26529@uwe> schreef in bericht news:662e9db6168db@uwe... >I have a multi-threaded application with a static constructor and static > DataSet and DataView variables, populated in the constructor. > i then create many threads to access the static DataView but some of the > threads generate errors while others work. Here is the code for the sample > console app > > using System; > using System.Data; > using System.Threading; > > namespace DataViewTest > { > class DataViewTest > { > static DataSet _ds; > static DataView _dv; > > private volatile Thread _thread; > private string _name; > > static DataViewTest() > { > _ds = new DataSet(); > DataTable tableOne = new DataTable("TableOne"); > > tableOne.Columns.Add(new DataColumn("Force", typeof (int))); > tableOne.Columns.Add(new DataColumn("Section", typeof (string))); > tableOne.Columns.Add(new DataColumn("ApplicationID", typeof (string))); > tableOne.Columns.Add(new DataColumn("GroupID", typeof (int))); > tableOne.Columns.Add(new DataColumn("Name", typeof (string))); > > DataRow newRow = tableOne.NewRow(); > newRow["Force"] = 13; > newRow["Section"] = "0"; > newRow["ApplicationID"] = "FA"; > newRow["GroupID"] = 1; > newRow["Name"] = "ZZ"; > tableOne.Rows.Add(newRow); > > _dv = new DataView(tableOne, null, "GroupID", > DataViewRowState.CurrentRows); > > _ds.Tables.Add(tableOne); > _ds.AcceptChanges(); > } > > public DataViewTest(string threadName) > { > _name = threadName; > } > > internal void Run() > { > if(_dv[0]==null) > { > System.Diagnostics.Trace.WriteLine(string.Format("{0} FAILED", _name)); > } > else > System.Diagnostics.Trace.WriteLine(string.Format("{0} worked", _name)); > } > > internal void Start() > { > _thread = new Thread(new ThreadStart(Run)); > _thread.Name = _name; > _thread.IsBackground = true; > _thread.Start(); > } > } > > /// <summary> > /// Summary description for Class1. > /// </summary> > class Class1 > { > private static DataViewTest[] _workers; > > /// <summary> > /// The main entry point for the application. > /// </summary> > [STAThread] > static void Main(string[] args) > { > _workers = new DataViewTest[100]; > for (int ct=0; ct<_workers.Length; ct++) > { > _workers[ct] = new DataViewTest(string.Format("Thread '{0}'", ct)); > } > > for (int ct=0; ct<_workers.Length; ct++) > { > _workers[ct].Start(); > } > > while(true) > Thread.Sleep(1000); > > } > } > } > > > here is some sample output > Thread '0' worked > The thread 'Thread '0'' (0x1dd4) has exited with code 0 (0x0). > Thread '27' worked > The thread 'Thread '27'' (0x1f18) has exited with code 0 (0x0). > Thread '63' worked > Thread '6' worked > Thread '1' FAILED > The thread 'Thread '6'' (0x1e70) has exited with code 0 (0x0). > The thread 'Thread '1'' (0x1b08) has exited with code 0 (0x0). > Thread '3' FAILED > The thread 'Thread '3'' (0x14d8) has exited with code 0 (0x0). > Thread '11' worked > Thread '2' FAILED > The thread 'Thread '11'' (0x1d90) has exited with code 0 (0x0). > The thread 'Thread '2'' (0x1bd8) has exited with code 0 (0x0). > Thread '5' worked > > The documentation says that DataViews are threadsafe, so why is this > happening? Sometimes, everything is OK, but more often than not, at least > one > thread fails. > |
|
|
|
#3 |
|
Guest
Posts: n/a
|
But the DataTable is static in the example, once it is created and added to
the DataSet, it is never updated again. Since the DataSet containing the DataTable is itself static, I can see no reason why some threads fail and some do not. It's worth mentioning that the threads that fail tend to be the first few threads and the threads that work tend to be the later theads. |
|
|
|
#4 |
|
Guest
Posts: n/a
|
Shaeney,
What do you mean with static in this case, the real meaning of the word static or the use of the word static in C and C derived languages? Cor "Shaeney" <u26529@uwe> schreef in bericht news:663090874cdeb@uwe... > But the DataTable is static in the example, once it is created and added > to > the DataSet, it is never updated again. > > Since the DataSet containing the DataTable is itself static, I can see no > reason why some threads fail and some do not. It's worth mentioning that > the > threads that fail tend to be the first few threads and the threads that > work > tend to be the later theads. > |
|
|
|
#5 |
|
Guest
Posts: n/a
|
In this particular case, I think I mean both.
The DataSet and DataView variables are declared as static. Since the DataSet "belongs" to the Dataset, as a variable it is also static. And the other static is that the data contained within the table is static in as much as it does not change after initialisation. So my question would be since the variables are static and the data contained within the DataTable, and therefore the DataView, is static then how come some threads ( created and run first ) fail to see the data in the DataView while other threads ( created and run later ) can see the data? Hope this explains the problem clearly. It's been driving me nuts! -- Message posted via DotNetMonster.com http://www.dotnetmonster.com/Uwe/Fo...do-net/200609/1 |
|
|
|
#6 |
|
Guest
Posts: n/a
|
Hi Shaeney,
Hey man, it seems that you've found a documentation error. DataView read operation is *not* thread safe and it never was due to lazy caching. I'll escalate the issue. -- Miha Markic [MVP C#, INETA Country Leader for Slovenia] RightHand .NET consulting & development www.rthand.com Blog: http://cs.rthand.com/blogs/blog_with_righthand/ "Shaeney" <u26529@uwe> wrote in message news:662e9db6168db@uwe... >I have a multi-threaded application with a static constructor and static > DataSet and DataView variables, populated in the constructor. > i then create many threads to access the static DataView but some of the > threads generate errors while others work. Here is the code for the sample > console app > > using System; > using System.Data; > using System.Threading; > > namespace DataViewTest > { > class DataViewTest > { > static DataSet _ds; > static DataView _dv; > > private volatile Thread _thread; > private string _name; > > static DataViewTest() > { > _ds = new DataSet(); > DataTable tableOne = new DataTable("TableOne"); > > tableOne.Columns.Add(new DataColumn("Force", typeof (int))); > tableOne.Columns.Add(new DataColumn("Section", typeof (string))); > tableOne.Columns.Add(new DataColumn("ApplicationID", typeof (string))); > tableOne.Columns.Add(new DataColumn("GroupID", typeof (int))); > tableOne.Columns.Add(new DataColumn("Name", typeof (string))); > > DataRow newRow = tableOne.NewRow(); > newRow["Force"] = 13; > newRow["Section"] = "0"; > newRow["ApplicationID"] = "FA"; > newRow["GroupID"] = 1; > newRow["Name"] = "ZZ"; > tableOne.Rows.Add(newRow); > > _dv = new DataView(tableOne, null, "GroupID", > DataViewRowState.CurrentRows); > > _ds.Tables.Add(tableOne); > _ds.AcceptChanges(); > } > > public DataViewTest(string threadName) > { > _name = threadName; > } > > internal void Run() > { > if(_dv[0]==null) > { > System.Diagnostics.Trace.WriteLine(string.Format("{0} FAILED", _name)); > } > else > System.Diagnostics.Trace.WriteLine(string.Format("{0} worked", _name)); > } > > internal void Start() > { > _thread = new Thread(new ThreadStart(Run)); > _thread.Name = _name; > _thread.IsBackground = true; > _thread.Start(); > } > } > > /// <summary> > /// Summary description for Class1. > /// </summary> > class Class1 > { > private static DataViewTest[] _workers; > > /// <summary> > /// The main entry point for the application. > /// </summary> > [STAThread] > static void Main(string[] args) > { > _workers = new DataViewTest[100]; > for (int ct=0; ct<_workers.Length; ct++) > { > _workers[ct] = new DataViewTest(string.Format("Thread '{0}'", ct)); > } > > for (int ct=0; ct<_workers.Length; ct++) > { > _workers[ct].Start(); > } > > while(true) > Thread.Sleep(1000); > > } > } > } > > > here is some sample output > Thread '0' worked > The thread 'Thread '0'' (0x1dd4) has exited with code 0 (0x0). > Thread '27' worked > The thread 'Thread '27'' (0x1f18) has exited with code 0 (0x0). > Thread '63' worked > Thread '6' worked > Thread '1' FAILED > The thread 'Thread '6'' (0x1e70) has exited with code 0 (0x0). > The thread 'Thread '1'' (0x1b08) has exited with code 0 (0x0). > Thread '3' FAILED > The thread 'Thread '3'' (0x14d8) has exited with code 0 (0x0). > Thread '11' worked > Thread '2' FAILED > The thread 'Thread '11'' (0x1d90) has exited with code 0 (0x0). > The thread 'Thread '2'' (0x1bd8) has exited with code 0 (0x0). > Thread '5' worked > > The documentation says that DataViews are threadsafe, so why is this > happening? Sometimes, everything is OK, but more often than not, at least > one > thread fails. > |
|
|
|
#7 |
|
Guest
Posts: n/a
|
Yeah, I thought as much. For now my work around will be to execute the Find
method on the DataView after I create it in the static constructor. This should force the lazy initialisation. Not exactly the solution I was hoping for... -- Message posted via DotNetMonster.com http://www.dotnetmonster.com/Uwe/Fo...do-net/200609/1 |
|
|
|
#8 |
|
Guest
Posts: n/a
|
Hi Shaeney,
"Shaeney via DotNetMonster.com" <u26529@uwe> wrote in message news:6638d516c4dfe@uwe... > Yeah, I thought as much. For now my work around will be to execute the > Find > method on the DataView after I create it in the static constructor. This > should force the lazy initialisation. > > Not exactly the solution I was hoping for... I would opt for a proper thread sync instead - use the lock statement any you'll be on the safe side (of course, this goes for acessing/modifyin underlying datatable/dataset too). The reason is that there might be other thread-safety problems in there. -- Miha Markic [MVP C#, INETA Country Leader for Slovenia] RightHand .NET consulting & development www.rthand.com Blog: http://cs.rthand.com/blogs/blog_with_righthand/ |
|
|
|
#9 |
|
Guest
Posts: n/a
|
Miha,
Won't probably not work, every row change can affects the dataview by instance the "sort" property in that, which is set by just clicking on a datagrid in an UI. Cor "Miha Markic [MVP C#]" <miha at rthand com> schreef in bericht news:eV79HUx1GHA.2176@TK2MSFTNGP04.phx.gbl... > Hi Shaeney, > > "Shaeney via DotNetMonster.com" <u26529@uwe> wrote in message > news:6638d516c4dfe@uwe... >> Yeah, I thought as much. For now my work around will be to execute the >> Find >> method on the DataView after I create it in the static constructor. This >> should force the lazy initialisation. >> >> Not exactly the solution I was hoping for... > > I would opt for a proper thread sync instead - use the lock statement any > you'll be on the safe side (of course, this goes for acessing/modifyin > underlying datatable/dataset too). The reason is that there might be other > thread-safety problems in there. > > -- > Miha Markic [MVP C#, INETA Country Leader for Slovenia] > RightHand .NET consulting & development www.rthand.com > Blog: http://cs.rthand.com/blogs/blog_with_righthand/ > |
|
|
|
#10 |
|
Guest
Posts: n/a
|
I am lucky that this is a service application we are talking about, so for my
particular case, with everything static, calling the find method in the static constructor will work for me. I dont have any worries about data grids. Of course, this does not help anyone else. i would suggest that they have a thread instance DataView rather than a static one, although I believe there is also an issue with many DataViews on a single DataSet ( with a hotfix ). -- Message posted via DotNetMonster.com http://www.dotnetmonster.com/Uwe/Fo...do-net/200609/1 |
|
![]() |
|
| Thread Tools | |
| Rate This Thread | |
|
|

Main Page 

