Synchronization Issue

I am running a method that downloads and stores IP information in a global table (code below).  At first I thought the issue was due to my use of a child thread to call this method but the error occurs even when running on the main thread.  The ecpetion itself is:

Object synchronization method was called from an unsynchronized block of code

As is coming up when attempting to Exit my lock - can somebody please help?
bool haveIt = Monitor.TryEnter(myTable, 1000);
while (!haveIt)
{
    //Just hang out...
    haveIt = Monitor.TryEnter(myTable, 1000);
}

if (haveIt)
{
    try
    {
        //DO WORK HERE 

    }
    catch (Exception throwIt)
    {
        throw throwIt;
    }
    finally
    {
	//This causes the error
        Monitor.Exit(myTable);
    }
}

Open in new window

ktolaAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Sarkany0Commented:
Hi. There can be only 2 errors with the Exit method.

http://msdn.microsoft.com/en-us/library/system.threading.monitor.exit%28v=VS.71%29.aspx

And by the way, you don't have to check if haveIt is true, you don't leave while while it isn't true, it just slows a bit down your program.

Bye
0
Sarkany0Commented:
Also this should work:
while (!Monitor.TryEnter(myTable, 1000));
0
ktolaAuthor Commented:
I understand that I do not need the haveIt value at all - it was there for debugging purposes and really has nothing to do with the issue.
If you review the reasons for failure, if a lock does not occur then the TryEnter would never return True and the Exit would never fire.  Therefore the issue has to be a null reference exception.
I am not sure but I think that the issue is the DataTable and that it somehow is changing pointers when datarows are being added to it.  Thus when I call Exit, somehow the pointer is being lost - again I do not know and, since this datatable is a global variable, that also does not make but so much sense.
Are there known issues with locking a datatable?
0
OWASP: Avoiding Hacker Tricks

Learn to build secure applications from the mindset of the hacker and avoid being exploited.

Sarkany0Commented:
You could provide us with extra information. For example what database are you using? What type myTable is? How do you connect to the database? For example.

And i'd suggest to you to check this out:

http://msdn.microsoft.com/en-us/library/system.threading.synchronizationlockexception%28v=VS.71%29.aspx
0
Sarkany0Commented:
0
ktolaAuthor Commented:
I appreciate your comments but I think you are way off base with the issue,  First I am completely disconnected from any data and I have distinct processes for writing out my persistent store.  Second, nothing that is occurring actually stores data.  In this case, the work is reading a web service call and transporting the incoming XML into a global DataTable called myTable.
I think the problem probably revolves around collisions between two child threads and I am now investigating Mutex as an option to overcome this limitation.  Unfortunately, I do not know much about Mutex and it appears that C# 3.5 has changed the rules...
0
VoloxCommented:
Is there a reason to use the Monitor other than just using the lock statement...

If there is timeout code in your while loop or something like that, then I can understand; but otherwise it seems like you might just be making your life more difficult than it needs to be.

lock (myTable) 
{ 
    try 
    { 
        //DO WORK HERE  
 
    } 
    catch (Exception throwIt) 
    { 
        throw throwIt; 
    } 
}

Open in new window

0
VoloxCommented:
You must be doing something else within that block of code (or outside it) that is causing the problem.  I took the sample code above and ran it and didn't get any error.  If within that try block or within code running in another thread you are doing something that changes the varaible myTable to point to a different object, that would produce the error you are getting.

If you do a myTable = new DataTable()
or if your 'real' code is something like Monitor.TryEnter(myDataSet.Tables[0], 1000) and somewhere myDataSet gets changed either by assigning it a new dataset or creating a new table.
or if you have the initial creating of the myTable variable inside of your try-catch

If you are trying to make myTable a global object that doesn't get created by more than one thread, then you need two critical sections rather than one...

class Program
{
	object tableCreationLock = new object();
	DataTable myTable;

	static void Main(string[] args)
	{
		Program p = new Program();

		p.DoThis();
	}

	public void DoThis()
	{
		// Check outside of the lock first to avoid slowing
		// thread down after the object has been created
		if ( null == myTable )
		{
			lock (tableCreationLock)
			{
				if (null == myTable)
				{
					// Create / load table
					myTable = new DataTable();
				}
			}
		}

		bool haveIt = Monitor.TryEnter( myTable, 1000 );
		while (!haveIt)
		{
			//Just hang out... 
			haveIt = Monitor.TryEnter( myTable, 1000 );
		}

		if (haveIt)
		{
			try
			{
				//DO WORK HERE  
				System.Console.WriteLine( "Work" );
			}
			catch (Exception throwIt)
			{
				throw throwIt;
			}
			finally
			{
				//This causes the error 
				Monitor.Exit( myTable );
			}
		}
		System.Console.WriteLine( "Done" );
	}
}

Open in new window

0
VoloxCommented:
Oh, and I'd also mention that if myTable is meant to be a static global object (not a class member variable like I have here) then your tableCreationLock object ought to be created as a static varaible and should be initialized within the static class constructor to ensure thread safety.  Per Microsoft the static constructor will be called only once per application domain...  http://msdn.microsoft.com/en-us/library/aa645612.aspx
And here is a good explanation of why this should be done in the static constructor rather than initializing the static field...
http://ondotnet.com/pub/a/dotnet/2003/07/07/staticxtor.html 
Hope that helps with the threading...
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ktolaAuthor Commented:
It turns out that the issue actually revolved around the upper level UI spawning threads that, in turn, were all interacting with a Singleton business object.  That business object contained the code that startted this thread and there is apparently no way for this level of complexity to be controlled.  
The fundamental issue is a blocking issue wherein a timer could launch a thread that could, in turn, launch numerous other threads to take care of various tasks.  The user could also launch a completely separate set of threads to accomplish similar tasks, etc...
I ended up scrapping the DataTable and, instead, I created a custom class that utilizes a series of Stack pointers to manage access to shared data.  In this way it does not matter what thread is trying to do work - I simply spool those requests inside the custom class and process them as I can.
0
ktolaAuthor Commented:
Thank you for all of the effort!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.