Solved

2 threads updating one object

Posted on 2007-12-05
14
207 Views
Last Modified: 2013-12-16
i have 2 threads one updates a dataset so information on a primary gridview can be updated and viewed while other data loading occurs.
the 2nd thread updates the same dataset so that information on a secondary gridview is loaded. the problem is that the while loop in the threads skips out updating the dataset. will loop (like) 9 times with out actually updating the ds.

we are grabing information from a wcf service using paging fill.  and to get the bindings to controls to stay we have to pass it a temporary ds by ref and then merge that into the forms base dataset. everytime we loop we clear the pertinent datatable in the temporary ds to get ready for a new page of data. this seems to be the issue. sometimes the threads while loop will go back through and hit that before the merge actually occurs, thereby erasing the data that we need to proceed.

hopefully someone can help, and i know that this hasn't been explained the best so let me know what you need.
0
Comment
Question by:p_davis
  • 9
  • 5
14 Comments
 
LVL 40

Expert Comment

by:evilrix
ID: 20414427
0
 
LVL 40

Accepted Solution

by:
evilrix earned 500 total points
ID: 20414548
The code below is a working example of how a mutex synchronizes threads. Without it the output is a mess. With it each thread outputs 10 lines and then defers to the other. To see the difference comment out the bits I've noted in the code.
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Text.RegularExpressions;

using System.Threading;
 
 

namespace cs_console

{

    class Program

    {

        static bool bQuit = false;

        static Mutex mtx = new Mutex(false);
 

        static void ThreadFunc()

        {

            while (!bQuit)

            {

                for (int x = 0; x < 10; ++x)

                {

                    //////////////////////////////////////////////////

                    // Comment out to see what it's like with no mutex

                    mtx.WaitOne();

                    //////////////////////////////////////////////////

                    for (int y = 0; y < 10; ++y)

                    {

                        Console.WriteLine("In thread: " + y.ToString());

                        Thread.Sleep(0);

                    }

                    //////////////////////////////////////////////////

                    // Comment out to see what it's like with no mutex

                    mtx.ReleaseMutex();

                    //////////////////////////////////////////////////

                }

            }

        }

        static void Main(string[] args)

        {

            Thread thread = new Thread(new ThreadStart(Program.ThreadFunc));

            thread.Start();
 

            for (int x = 0; x < 10; ++x)

            {

                //////////////////////////////////////////////////

                // Comment out to see what it's like with no mutex

                mtx.WaitOne();

                //////////////////////////////////////////////////

                for (int y = 0; y < 10; ++y)

                {

                    Console.WriteLine("In main: " + y.ToString());

                    Thread.Sleep(0);

                }

                //////////////////////////////////////////////////

                // Comment out to see what it's like with no mutex

                mtx.ReleaseMutex();

                //////////////////////////////////////////////////

            }
 

            bQuit = true;
 

            thread.Join();

        }

    }

}

Open in new window

0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414579
If you just want one thread to signal the other thread when to clear the ds, consider using an AutoResetEvent: -

http://msdn2.microsoft.com/en-us/library/system.threading.autoresetevent.aspx

0
 
LVL 22

Author Comment

by:p_davis
ID: 20414740
thanks for the ideas i will try. i had been messing with locks and monitor but nothing seemed to work the way i thought it should.

should the mutex calls be wrapped in a try/finally block so the release always gets called?
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414751
The following example uses 2 auto reset events to pass signals between main and thread. Comments in the code should clarify what is going on: -
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Text.RegularExpressions;

using System.Threading;
 
 

namespace cs_console

{

    class Program

    {

        static bool bQuit = false;

        static Mutex mtx = new Mutex(false);

        static AutoResetEvent autoEventThread = new AutoResetEvent(false);

        static AutoResetEvent autoEventMain = new AutoResetEvent(false);
 

        static void ThreadFunc()

        {

            while (!bQuit)

            {

                for (int x = 0; x < 10; ++x)

                {

                    //////////////////////////////////////////////////////

                    // Wait for main to signal

                    autoEventThread.WaitOne();

                    //////////////////////////////////////////////////////
 

                    if (!bQuit)

                    {

                        //////////////////////////////////////////////////

                        // Comment out to see what it's like with no mutex

                        mtx.WaitOne();

                        //////////////////////////////////////////////////

                        for (int y = 0; y < 10; ++y)

                        {

                            Console.WriteLine("In thread: " + y.ToString());

                            Thread.Sleep(0);

                        }

                        //////////////////////////////////////////////////

                        // Comment out to see what it's like with no mutex

                        mtx.ReleaseMutex();

                        //////////////////////////////////////////////////

                        // Signal main

                        autoEventMain.Set();

                        //////////////////////////////////////////////////

                    }

                }

            }

        }

        static void Main(string[] args)

        {

            Thread thread = new Thread(new ThreadStart(Program.ThreadFunc));

            thread.Start();
 

            for (int x = 0; x < 10; ++x)

            {

                //////////////////////////////////////////////////

                // Use event to ensure main runs before thread

                // and do two main loops to one thread loop

                if ((x > 0) && (x % 2) == 0)

                {

                    // Signal thread

                    autoEventThread.Set();

                    // Wait for thread to signal

                    autoEventMain.WaitOne();

                }

                //////////////////////////////////////////////////

                // Comment out to see what it's like with no mutex

                mtx.WaitOne();

                //////////////////////////////////////////////////

                for (int y = 0; y < 10; ++y)

                {

                    Console.WriteLine("In main: " + y.ToString());

                    Thread.Sleep(0);

                }

                //////////////////////////////////////////////////

                // Comment out to see what it's like with no mutex

                mtx.ReleaseMutex();

                //////////////////////////////////////////////////

            }
 

            bQuit = true;
 

            //////////////////////////////////////////////////////

            // Signal thread

            autoEventThread.Set();

            //////////////////////////////////////////////////////
 

            thread.Join();

        }

    }

}

Open in new window

0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414761
>> should the mutex calls be wrapped in a try/finally block so the release always gets called?
You need to ensure your code is exception safe. I've left that out for clarity.
0
 
LVL 22

Author Comment

by:p_davis
ID: 20414843
ok, that seems to work better but it also seems creates a problem that i saw earlier

after loading the data i have to sort the primary grid so the data shows (otherwise it is just blank)
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 22

Author Comment

by:p_davis
ID: 20414852
meaning i have to manually click on the column header on the grid that is on the  ui.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414867
>> ok, that seems to work better but it also seems creates a problem that i saw earlier
Creates or shows up existing?
0
 
LVL 22

Author Comment

by:p_davis
ID: 20414949
before the way i was doing it it would load after a certain amount of time but it would loop through with the clearing the datatable several times and then it would go through.
you could see the data actively being loaded into both gridviews but now you can't until you click on the column header

>>Creates or shows up existing?
i guess it could be debatable, but i'm hoping we won't as i would like to know how to correct this
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414982
Using try/finally to ensure code is exception safe...
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Text.RegularExpressions;

using System.Threading;

 

 

namespace cs_console

{

    class Program

    {

        static bool bQuit = false;

        static Mutex mtx = new Mutex(false);

 

        static void ThreadFunc()

        {

            while (!bQuit)

            {

                for (int x = 0; x < 10; ++x)

                {

                    if (!bQuit)

                    {

                        try

                        {

                            //////////////////////////////////////////////////

                            // Comment out to see what it's like with no mutex

                            mtx.WaitOne();

                            //////////////////////////////////////////////////

                            for (int y = 0; y < 10; ++y)

                            {

                                Console.WriteLine("In thread: " + y.ToString());

                                Thread.Sleep(0);

                            }

                            //////////////////////////////////////////////////

                        }

                        finally

                        {

                            //////////////////////////////////////////////////

                            // Comment out to see what it's like with no mutex

                            mtx.ReleaseMutex();

                            //////////////////////////////////////////////////

                        }

                    }

                }

            }

        }

        static void Main(string[] args)

        {

            Thread thread = new Thread(new ThreadStart(Program.ThreadFunc));

            thread.Start();

 

            for (int x = 0; x < 10; ++x)

            {

                try

                {

                    //////////////////////////////////////////////////

                    // Comment out to see what it's like with no mutex

                    mtx.WaitOne();

                    //////////////////////////////////////////////////

                    for (int y = 0; y < 10; ++y)

                    {

                        Console.WriteLine("In main: " + y.ToString());

                        Thread.Sleep(0);

                    }

                    //////////////////////////////////////////////////

                }

                finally

                {

                    //////////////////////////////////////////////////

                    // Comment out to see what it's like with no mutex

                    mtx.ReleaseMutex();

                    //////////////////////////////////////////////////

                }

            }

 

            bQuit = true;

 

            thread.Join();

        }

    }

} 

Open in new window

0
 
LVL 40

Expert Comment

by:evilrix
ID: 20415004
>> i guess it could be debatable, but i'm hoping we won't as i would like to know how to correct this
Well, I think it's fair to say it's probably an existing issue that has now manifested due to introduction of synchronization. I'm not sure I can help you out with that. I think you'll need to do a little debugging unfortunately.
0
 
LVL 22

Author Comment

by:p_davis
ID: 20415031
no matter, thank you for your posts.  the last part-- all i did was reset the bindings on the bindingsource and the data loaded fine.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20415100
>> all i did was reset the bindings on the bindingsource and the data loaded fine.
Great, I'm glad you figured that out. That kind of stuff -- not my strength :)
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

We all know that functional code is the leg that any good program stands on when it comes right down to it, however, if your program lacks a good user interface your product may not have the appeal needed to keep your customers happy. This issue can…
Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now