Click here to Skip to main content
15,880,972 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am new to threading in C# and I would like some help with making this code thread-safe.

C#
Thread AGetData;
        public void Get()
        {
            SetA_TimeSteps.Items.Clear();
            SetA_InformationTree.Nodes[2].Nodes[1].Nodes.Clear();
            Capabilities.Load("http://datapoint.metoffice.gov.uk/public/data/layer/wxobs/all/xml/capabilities?key=14963e76-bad2-49ca-8c12-f47afd52deee");
            for (int x = 0; x < Capabilities.SelectNodes("/Layers/Layer[@displayName='Rainfall']/Service/Times/Time").Count; x++)
            { SetA_TimeSteps.Items.Add(Capabilities.SelectNodes("/Layers/Layer[@displayName='Rainfall']/Service/Times/Time")[x].InnerText); }
            SetA_LayerImage.LoadAsync(FUNCTIONS.CreateMapURL("obs", "RADAR_UK_Composite_Highres", "png", SetA_TimeSteps.Items[0].ToString()));
            SetA_TimeSteps.SelectedIndex = 0;
            SetA_LastLive = SetA_TimeSteps.Items[0].ToString();
            SetA_LayerImage.Enabled = true;
            SetA_TimeSteps.Enabled = true;
            SetA_PrepareAnimation.Enabled = true;
            SetA_ExportMapData.Enabled = true;
            SetA_ExportDataOverlay.Enabled = true;
            SetA_ExportDataInformation.Enabled = true;
            foreach (string item in SetA_TimeSteps.Items)
            { SetA_InformationTree.Nodes[2].Nodes[1].Nodes.Add(item.ToString()); }
            SetA_InformationTree.ExpandAll();
        }

        // ---GetData_Click---
        private void SetA_GetData_Click(object sender, EventArgs e) //A---
        {
            AGetData = new Thread(Get);
            AGetData.Start();
            Throbber.ShowDialog();            
        }


What should happen is like this: When I click the GetData button (SetA_GetData_Click), it should start a separate thread (AGetData). The original thread should show a loading form with an animated gif on to tell the user it is loading and should close when the new thread has finished doing the work. The new thread should set all of the properties on the controls and get the resources from the xml files online.

The main form is on the original thread and contains all of the controls I want to set from a new thread. I don't want to use a BackgroundWorker. The main problem is how to make the code thread-safe and how to close the loading form when the new thread has finished. I also would lie this thread to be reusable. Hope this makes sense, thank you.
Posted

It's a good idea to reuse a thread. (But remember that another option is to use the thread pool.)

If you need a thread to be reused during the full time of the application, you can create one at the very beginning and throttle when it is not needed. What you need to do is to put it in a wait state. It switched a thread out and not scheduled back to execution until it is awaken, which happens on different conditions, in particular, timeout and abort. You can use the class System.Threading.ManualResetEvent:
http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx[^].

When you put an event in a non-signaled state and some thread calls its WaitOne method, it will put the thread in a wait state, and awake that thread when the event is set signaled by some other thread. I hope you got the idea: you signal the event when you have some work for this thread to do.

See also my past answers on this topic:
ManualResetEvent and AutoResetEvent in Thread[^],
pause running thread[^].

You may need more high-level implementation of such mechanism. A well-known method of feeding tasks to a thread is a blocking queue. You can find full source code and implementation in my article: Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

With .NET 4.0, you can use Concurrent.BlockingCollection instead, please see the alternative to my article:
http://www.codeproject.com/script/Articles/ListAlternatives.aspx?aid=149540[^].

Note that with .NET you can also feed the delegate instances and invoke them on the other thread as they are fed to the thread. This is the most advanced and easiest to use method of reusing threads. My article is complete with usage samples explaining the technique.

Also, it is very beneficial to use a thread via a thread wrapper. Please see my past answers:
How to pass ref parameter to the thread[^],
Change parameters of thread (producer) after it is started[^],
MultiThreading in C#[^].

Now, synchronization with the UI… Oddly enough, the mechanism is very similar to the solution with blocking queue, only the queue is non-blocking: this is the event queue of a UI thread. I'll explain:

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

For other thread synchronization chores, use usual synchronization primitives. Remember though: best synchronization is no synchronization. No, I'm not suggesting ignoring thread safety, never. Instead, you should design the code in as parallel way as possible: try to use functional style, do everything on stack, avoid static data, and so on. In other words, reduce the need for synchronization.

—SA
 
Share this answer
 
Comments
Menon Santosh 1-Sep-13 13:36pm    
my +5
Sergey Alexandrovich Kryukov 1-Sep-13 13:56pm    
Than you, Menon.
—SA
V.Lorz 2-Sep-13 3:34am    
Mine too.
Sergey Alexandrovich Kryukov 2-Sep-13 10:18am    
Thank you.
—SA
Hi I think you should start here Threading in C#[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900