 |
| .NET Framework 2.0 For discussion of the Microsoft .NET Framework 2.0. |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the .NET Framework 2.0 section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|
|

July 21st, 2008, 02:41 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 217
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Queue or how to syncronize without locking
Hi all.
I'm re-developing a Data Access Layer Manager (codeplex.com/dalm) and have some architectural doubts about some of the I/O operations.
The problem
All queries are read from an XML file which is loaded into memory on first run. When a query is requested to be executed, the DALM will read from memory. Now, if the query doesn't exist in memory, the XML file has to be read again. But while reading the XML file, queries that does exist in memory should still be retrieved and executed. I have been using ADO.NET DataSet to read XML until now.
1st solution
When the a query is not found, the thread will continue to a "read xml statement" which will be locked using the lock keyword. This way other treads will still be able to access the DataSet. The problem is that the threads that also didn't find their query will continue to a "read xml statement". A solution could be to load all the threads into an Array, fire an event which will load the XML and then call the "find query" method recursively. The array would function as a Queue.
But how does threads behave when you put them in an array? Won't they continue? And if I continue to use DataSet, won't there be a moment where threads will get access denied exceptions, when I change the reference to the new DataSet? Loading grafs XML is not an option as I want the XML file to be human editable, ie. simple.
2nd solution
Dunno - something better? Maybe there is a pattern that doesn't require any locking at all?? I've looked into immutable stacks ( http://blogs.msdn.com/ericlippert/ar...ble-stack.aspx) to see if I could somehow synchronize without locking but I'm not sure how to apply it to my problem.
I hope this triggers some ideas!
Thanks in advance, Jon
- mega
Moving to C# .NET
__________________
- mega
Aspiring JavaScript Ninja
|
|

July 21st, 2008, 05:46 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 217
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Maybe some code would help? Any questions or is it just too tough?
- mega
Moving to C# .NET
|
|

July 21st, 2008, 09:01 AM
|
 |
Friend of Wrox
|
|
Join Date: Aug 2003
Posts: 5,407
Thanks: 0
Thanked 16 Times in 16 Posts
|
|
Are you loading the entire XML file into memory? If so, I'm not seeing the need for threads or locking. I suppose it would be sensible to lock the file read and insert into memory step as that only needs to be done once. (To optimize that you'd probably want two checks on whether the file has been loaded: one prior to and one after the actual lock, as a blocked pass that thinks needs to load the file may no longer need to after it is unblocked by another pass that already did the load.)
What do you mean about how threads behave when in an array? What's in an array? A reference to the thread object? I don't imagine that would have any impact on what is actually happening in the thread itself. You just have list of references to them.
-Peter
compiledthoughts.com
|
|

July 21st, 2008, 09:54 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 217
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
The class that loads the XML file is static/Shared and loads the entire XML file into a DataSet in the constructor, so its always loaded before any methods is called. But you should still be able to modify the file without having to stop the application. I could check whether the file has been modified before reading from the DataSet but that would make the code slow as threads would need to be locked while checking.
In web scenarios there will always be multiple threads. The DALM retrieves the SQL statements (queries) from the XML file (or in memory) every time a query is executed. In my prototype version (can be downloaded from codeplex.com) I had a check before each request and then locked all threads until the XML file was read. This is what I'm trying to avoid.
About the array of threads, I had an idea that it might just work like that :(
While reading your post I came up with this, which might do the trick..
Code:
private static string LookUp(string queryname, LookUpType type)
{
DataTableReader reader = _querySet.CreateDataReader();
while (reader.Read())
{
if (reader["Name"].ToString().Equals(queryname))
{
switch (type)
{
case LookUpType.Query :
return reader["QueryText"].ToString();
case LookUpType.Database :
return reader["Database"].ToString();
}
}
}
// query not found in memory, update memory from QueryFile
lock (LookUpLock)
{
// could do a check here to see whether the file is loaded or not
_querySet.ReadXml(string.Format("{0}{1}.xml", QueryFileInfo.FilePath, QueryFileInfo.FileName));
}
// call this method again
return LookUp(queryname, type);
}
I'll just try it out and get back
- mega
Moving to C# .NET
|
|

July 21st, 2008, 10:54 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 217
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Ok, I got it working. Now I just have to watch out for System.StackOverflowException if the query can't be found. That will bring down the entire application. Any ideas?
Code:
private static string LookUp(string queryname, LookUpType type)
{
DataTableReader reader = _querySet.CreateDataReader();
while (reader.Read())
{
if (reader["Name"].ToString().Equals(queryname))
{
switch (type)
{
case LookUpType.Query :
Debug.WriteLine(string.Format("queryname = {0}, answer = {1}", queryname, reader["QueryText"].ToString()), "QueryReader");
return reader["QueryText"].ToString();
case LookUpType.Database :
Debug.WriteLine(string.Format("queryname = {0}, answer = {1}", queryname, reader["Database"].ToString()), "QueryReader");
return reader["Database"].ToString();
}
}
}
// query not found in memory, update memory from QueryFile
lock (LookUpLock)
{
FileInfo fi = new FileInfo(QueryFileInfo.QualifiedName);
if (QueryFileInfo.FileLastUpdated < fi.LastWriteTime)
{
ReadQueryFile();
QueryFileInfo.FileLastUpdated = fi.LastWriteTime;
}
}
// I had to have this while testing or I would get a StackOverflowException all the time!
System.Threading.Thread.Sleep(1000);
return LookUp(queryname, type);
}
private static void ReadQueryFile()
{
Debug.WriteLine(string.Format("Reading XML file at {0}", QueryFileInfo.QualifiedName), "QueryReader");
DataSet ds = new DataSet("Query");
ds.ReadXml(QueryFileInfo.QualifiedName);
_querySet = ds;
}
- mega
Moving to C# .NET
|
|

July 21st, 2008, 11:10 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 217
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Dunno if I'm getting off topic here but to avoid StackOverflowException, should I create an Array[][] with the thread ids and count,
so I can terminate the ones that run infinite? Or should I thrust the users to type in query names correctly?
- mega
Moving to C# .NET
|
|

July 21st, 2008, 02:28 PM
|
 |
Friend of Wrox
|
|
Join Date: Aug 2003
Posts: 5,407
Thanks: 0
Thanked 16 Times in 16 Posts
|
|
I'm perplexed by what you are doing.
You are going to loop indefinitely while users type in queries to be saved to an XML file? What is the purpose of this? I'm trying to come up with a logical reason for developing this kind of code.
Of course you are going to get a stack overflow the instant a query can't be found because you'll recurse forever (or until the stack crashes). It would seem logical that the call should simply throw an exception or something else if the query being asked for doesn't exist. If you recurse forever (even with a delay), how does the user (i.e. developer??) know that the query wasn't found? This echoes back on the "why are you doing this?" question above.
-Peter
compiledthoughts.com
|
|

July 22nd, 2008, 03:02 AM
|
 |
Friend of Wrox
|
|
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
|
|
One method would be to refactor your original method so that the dataset lookup is in a seperate method:
Code:
private static string LookUp(string queryname, LookUpType type)
{
string query = LookUpReal(queryname, type);
if( query != null ) return;
// query not found in memory, update memory from QueryFile
lock (LookUpLock)
{
FileInfo fi = new FileInfo(QueryFileInfo.QualifiedName);
if (QueryFileInfo.FileLastUpdated < fi.LastWriteTime)
{
ReadQueryFile();
QueryFileInfo.FileLastUpdated = fi.LastWriteTime;
}
}
return LookUpReal(queryname, type);
}
private static string LookUpReal(string queryname, LookUpType type)
{
DataTableReader reader = _querySet.CreateDataReader();
while (reader.Read())
{
if (reader["Name"].ToString().Equals(queryname))
{
switch (type)
{
case LookUpType.Query :
Debug.WriteLine(string.Format("queryname = {0}, answer = {1}", queryname, reader["QueryText"].ToString()), "QueryReader");
return reader["QueryText"].ToString();
case LookUpType.Database :
Debug.WriteLine(string.Format("queryname = {0}, answer = {1}", queryname, reader["Database"].ToString()), "QueryReader");
return reader["Database"].ToString();
}
}
}
return null;
}
/- Sam Judson : Wrox Technical Editor -/
|
|

July 23rd, 2008, 08:46 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 217
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Thanks to both of you. I'm gonna go with your suggestion Sam.
- thanks, jon
- mega
Moving to C# .NET
|
Similar Threads
|
| Thread |
Thread Starter |
Forum |
Replies |
Last Post |
| Message Queue vs. FTP |
andysc |
BOOK: Professional SQL Server 2005 Integration Services ISBN: 0-7645-8435-9 |
1 |
April 28th, 2008 07:23 PM |
| Circular queue |
bulletgreen |
BOOK: Professional C++ |
0 |
December 15th, 2005 04:28 AM |
| Array and the circular queue |
bidhya |
Java GUI |
0 |
May 13th, 2004 02:24 AM |
| double queue |
mafuka |
C++ Programming |
1 |
April 6th, 2004 01:08 PM |
| Printing queue |
Maximus |
Excel VBA |
1 |
August 15th, 2003 07:00 AM |
|
 |