Solved

2 threads updating one object

Posted on 2007-12-05
14
211 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
Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

 
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
 
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

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
C# Desktop Application 3 54
Syntax Issue with SSIS module 26 100
Open a link in vb.net 2 15
Where is this file? 3 25
More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
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…

791 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