views:

97

answers:

3

I have two working threads.I have locked both with a same lock, but threadB is getting executed before threadA, so exception came.I locked both using the same lock object.Thread B is using delegate function.How can I solve the issue.

Detailed Information:


I have a class called StateSimulation. Inside that there are two functions called a) OnSimulationCollisionReset b) OnSimulationProgressEvent

Implementation is like this:

private void OnSimulationCollisionReset()
{
    Thread XmlReset = new Thread(XmlResetFn);
    XmlReset.Start();
}

private void OnSimulationProgressEvent()
{
    DataStoreSingleTon.Instance.IsResetCompleted = true;
    Thread ThrdSimulnProgress = new Thread(SimulnProgress);
    ThrdSimulnProgress.Start();
}

where SimulnProgress() and XmlResetFn() are as follows:

private void SimulnProgress()
{
    //uses a delegate 
    UIControlHandler.Instance.ShowSimulationProgress();
}

private void XmlResetFn()
{
    DataStoreSingleTon.Instance.GetFPBConfigurationInstance().ResetXmlAfterCollision();
}

In which OnSimulationProgressEvent() is using a delegate function.

Both showSimulationProgress and ResetXML...() uses a same resource FPBArrayList.

My requirement is SimulationProgressEvent() should work only after Reset..(). In resetXML..() I clear the FPBList. In SimulationProgress() I access FPBList[i] where i:0--->size; I have locked both functions using a same lock object.I expected, reset() will complete first. But after entering to reset, before complete reset, showProgress() started and exception occured..

How to solve my issue?

This is how I locked the functions

public System.Object lockThis = new System.Object();

private void SimulnProgress()
{
    lock (lockThis)
    {
        UIControlHandler.Instance.ShowSimulationProgress();
    }
}

private void XmlResetFn()
{
    lock (lockThis)
    {
        DataStoreSingleTon.Instance.GetFPBConfigurationInstance().ResetXmlAfterCollision();
    }
}

Please give a solution. Regards Nidhin KR

+2  A: 

Locks are intended to prevent several threads from entering a given section of code simultaneously. They are not intended to synchronize the threads in any other way, like, making them execute code in some specific order.

To enforce the execution order you need to implement some signalling between your threads. Have a look at Synchronization Primitives, specifically, Auto/ManualResetEvent is probably what you want.

VladV
+2  A: 

It's not a good idea to write multithreaded code that assumes or requires that execution on different threads occurs in a particular order. The whole point of multithreading is to allow things to be executed independently of each other. Independently means no particular order is expressed or implied. CPU time might not be distributed evenly between the two threads, for example, particularly is one thread is waiting for an external signaling event and the other thread is in a compute loop.

For your particular code, it seems very odd that IsResetCompleted = true; is set in the OnSimulationProgressEvent handler. The completion state of the Reset activity should be set by the Reset activity, not by some other event executing in another thread assuming "If we're here, the work in the other thread must be finished."

You should review your design and identify your assumptions and dependencies between threads. If thread B must not proceed until after thread A has completed something, you should first reexamine why you're putting this work in different threads, and then perhaps use a synchronization object (such as an AutoResetEvent) to coordinate between the threads.

The key point here is if you take a sequential task and split it into multiple threads, but the threads use locks or synch objects to serialize their execution, then there is no benefit to using multiple threads. The operation is still sequential.

dthorpe
+2  A: 

I am not sure if I understand the question entirely, but if your requirement is simply that you want to prevent the body of SimulnProgress from executing before XmlResetfn has executed at least once, you can do:

public readonly object lockThis = new object();
private readonly ManualResetEvent resetHandle = new ManualResetEvent(false);

private void SimulnProgress()
{
    resetHandle.WaitOne();

    lock (lockThis)
    {
        UIControlHandler.Instance.ShowSimulationProgress();
    }
}

private void XmlResetFn()
{
    lock (lockThis)
    {
        DataStoreSingleTon.Instance.GetFPBConfigurationInstance().ResetXmlAfterCollision();
    }

    resetHandle.Set();
}
Ani