简体   繁体   中英

c# Thread syncronization problem

So I'm seeing fun stuff playing with threads.

I have a method that starts 2 threads and goes on with its life and I tried doing the following to keep things safe.

    bool CopyOk1 = false;
    bool CopyOk2 = false;
    new Thread(() => FirstMethod(tempList1, ref CopyOk1)).Start();
    new Thread(() => SecondMethod(tempList2, ref CopyOk2)).Start();
    var spinner = new SpinWait();
    while (!CopyOk1 || !CopyOk2)
        spinner.SpinOnce();

then in both methods I start with the following

    private static void FirstMethod(List<T> templist, ref bool CopyOk)
    {
        var temp = new T[templist.Count];
        templist.CopyTo(temp);
        CopyOk = true;
        //moves on
    }

My intention here is to copy the passed list so I can change and use it safely inside the threads ASAP to unblock the caller thread.

My problem is that on the second method unpredictably, between the array initialization and the list CopyTo the base list changes, somehow, by something.

These lists are created inside the caller thread and are not actually used after the threads are started so I have absolutely NO idea how/why this is happening.

No doubt I'm doing something wrong here, but my noobish skills won't let me see, any help is appreciated.

Instead of locking 'templist', use a global lock. Then protect all code that modifies the source list with that same lock.

Also, perhaps an aside, but waiting for a thread to partially complete can be done more elegantly, ie not involving a loop. Using a ManualResetEvent will allow your original thread to wait for 'something' to occur in other threads. Using WaitOne will block the thread until a Set() is called in the other thread.

private object m_Lock = new object();
private ManualResetEvent m_ResetOne = new ManualResetEvent(false);
private ManualResetEvent m_ResetTwo = new ManualResetEvent(false);

(...)

new Thread(() => FirstMethod(tempList1)).Start();
new Thread(() => SecondMethod(tempList2)).Start();
m_ResetOne.WaitOne();
m_ResetTwo.WaitOne();

(...)

private void FirstMethod(List<T> templist)
{
    lock (m_Lock)
    {
        var temp = new T[templist.Count];
        templist.CopyTo(temp);
    }
    m_ResetOne .Set();
    //moves on
}

Nothing in the code that you posted suggests that you are doing anything wrong. The problem has to lie elsewhere- most likely, as commenters have suggested, in the code that populates List1/List2. If you are threading that as well, perhaps you are not waiting for that thread to finish populating the lists before proceeding?

Try this and check the behavior

private static void FirstMethod(List<T> templist, ref bool CopyOk)
{
    T[] temp;

    lock (templist)
    {
        temp = new T[templist.Count];
        templist.CopyTo(temp);
    }
    CopyOk = true;
    //moves on
}

You need some type of synchronization mechanism to prevent List<T> from being changed. We can't see enough code in the current sample to warrant that it is not being altered.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM