Click here to Skip to main content
15,879,348 members
Please Sign up or sign in to vote.
3.50/5 (2 votes)
See more:
hi,

I'm trying to execute two different threads that are inserting into two different tables. The problem I'm having is that my entire CPU usage is being consumed (100%)...I'm definitely sure that the code I've written is full of errors and incorrect. Can someone please explain/show me the correct way to go about this.

Thank you!

-Donald

here's the sample code:

Data Tier:

    class DataAccessLayer
    {
        public SqlConnection conn;
        public SqlCommand cmd;
        public int bidPrice;
        public int askPrice;
        public int lastPrice;

        public DataAccessLayer()
        {
            conn = new SqlConnection("Server = localhost; Database = testdb; uid = root; pwd = password; port = 0000;");
            cmd = new SqlCommand();
            try
            {
                conn.Open();
                cmd.Connection = conn;
            }
            catch
            {
                throw new Exception("Connection Error...");
            }
        }

        public void DataManipulation(object str)
        {
            string s = (string)str;
            List<string> data = new List<string>(s.Split(','));
            bidPrice = int.Parse(data[0]);
            askPrice = int.Parse(data[1]);
            lastPrice = int.Parse(data[2]);
        }

        public void Insert()
        {
            lock (this)
            {
                try
                {
                    cmd.CommandText = string.Format("INSERT INTO test_tbl VALUES (NULL,{0},{1},{2});", bidPrice, askPrice, lastPrice);
                    cmd.ExecuteNonQuery();
                }
                catch (SqlException ex)
                {
                    throw ex;
                }
            }
        }

        public void Update()
        {
            lock (this)
            {
                try
                {
                    cmd.CommandText = string.Format("INSERT INTO test_tbl2 VALUES (NULL,{0},{1},{2});", bidPrice, askPrice, lastPrice);
                    cmd.ExecuteNonQuery();
                }
                catch (SqlException ex)
                {
                    throw ex;
                }
            }
        }
    }


Main code:

MSIL
public partial class Form1 : Form
    {
        DataAccessLayer dataAccess;
        Thread updateThread;
        Thread insertThread;
        Thread dataThread;
        string dataString;

        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                dataAccess = new DataAccessLayer();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        private void onQuote()
        {
            while (true)
            {
                Random rnd = new Random();
                int bid = rnd.Next(10);
                int ask = rnd.Next(10);
                int last = rnd.Next(10);
                dataString = string.Format("{0},{1},{2}", bid, ask, last);
                updateThread = new Thread(new ThreadStart(dataAccess.Update));
                insertThread = new Thread(new ThreadStart(dataAccess.Insert));
                dataThread = new Thread(new ParameterizedThreadStart(dataAccess.DataManipulation));
                dataThread.Priority = ThreadPriority.AboveNormal;
                dataThread.Start(dataString);
                insertThread.Start();
                updateThread.Start();
            }
        }
        private void btnStart_Click(object sender, EventArgs e)
        {
            onQuote();
        }
    }
Posted
Updated 20-Jan-11 12:55pm
v7
Comments
Manfred Rudolf Bihy 20-Jan-11 20:40pm    
What Nishant told you is the truth. Since you're starting threads in an endless loop from onQuote method of course CPU will be going 100%. onQuote is started from the UI thread (click event from btnStart) so this is also the cause of your application seeming to freeze. I do hope you weren't the one who downvoted Nishant's answer.
If you don't want your application to freeze you'll have to start a background thread from the buttons click event. It might also help to introduce a small pause in the loop in onQuote (Thread.Sleep(10) for instance) to keep the CPU usage go to 100%.
Sergey Alexandrovich Kryukov 20-Jan-11 20:45pm    
Despite of crazy design attempt, I like the question itself. My vote is "4"
d.allen101 20-Jan-11 20:52pm    
yes I was and I feel REALLY stupid! is there anyway, I change my vote? and I apologize for being arrogant and not listing!
Sergey Alexandrovich Kryukov 20-Jan-11 21:08pm    
You can re-vote any time (to get voting radio button available to you again, just re-load the page). If you voted "1" (I'm not sure), it would be a little too much of emotional criticism for that answer :-)

No wonder you have problem of CPU consumption. I also think that your UI is hanging forever after btnStart clicked, is that right?

I appreciate you mature understanding that your design is far from perfect at the moment. I can tell you could not make more correct assumption than that :) .

To give you a first hint, I can tell that the method onQuote itself should run is separate thread; and this thread is more important that your threads running Update, Insert and DataManipulation; it also need a condition for termination. But as a next step, we need to understand if we need the method like onQuite at all -- I don't think so.

First of all, you try to create unwanted parallelism. Also you created unpredictable number of threads: you created them with not condition. Try to count how many thread are currently active -- result is unpredictable. Imagine the time between start and finish of your threads is faster than the loop of onQuote (which can be realistic). You create thread faster then they are exit their processing. It means you will create infinite number of thread, in practice, until you get your OS into resource stress beyond normal operational limits. It's not 100% CPU consumption, it's worse. But what really amaze me is: do you really employ the parallelism and gain any performance? Only in the very beginning at best; most of the time you slow down due to over-consumption of your system resources (creation of the thread along is too expensive to run this API in cycle).

Before we go any further, let me give you few hints in advance:
I would say, you need fixed number of threads; and in you need to created about 3*N thread, where N is the number of tables. This is very approximate reasonable estimate; and such thread arrangement is may vary depending of your task detail. Also, you need to creates all threads at the very beginning and start only once. Threads should be kept sleeping and wake up only when their input data is fed to them. It means you need to use some synchronization primitives (I would suggest EventWaitHandle) and the queues of data between them. In principle, you can use some messaging system and/or such option as WCF, but I would prefer to design those data queues and synchronization by hand -- it's not too hard. It looks like a complication, but let me explain: the alternative will be letting your thread off the leash and consuming everything around.

Another issue is thread priority. Generally, it is recommended not to touch it. It would not help. In your case, this is certainly a correct rule.

Before going to further detail, let me tell you about one problem. It looks like you model some sensible task with some experimental toy problem. Do you think it it realistic enough for demonstration and evaluation of the techniques? It is not. It's good enough for demonstration of crazy consuming-all threading, but for more balanced design it's good to overview more realistic goal. I don't know what. I would prefer you lean a bit to your real-life application goals. Just think about it, then we can continue with some detail...

[EDIT]

As other people asked somewhat similar questions, I decided to add another answer, this time with some code. It will provide some details on inter-thread communications I mentioned above.

Thank you.
--SA
 
Share this answer
 
v7
Comments
Manfred Rudolf Bihy 20-Jan-11 20:48pm    
I see you came to the same conclusions! 5+
Sergey Alexandrovich Kryukov 23-Jan-11 17:12pm    
Please see my other Answer and my new article in Tips & Tricks (referenced).
Nish Nishant 20-Jan-11 20:51pm    
5! Great response!
Sergey Alexandrovich Kryukov 20-Jan-11 20:55pm    
Donald, I think we all need to digest all this (especially you), think around the answers we already have and discussion and then discuss a little further. You problem is quite solvable, we only need to put all aspects together and be careful with designs. Let's do it a little later.

Your feedback is expected and very welcome.
Respectfully,
--SA
Sergey Alexandrovich Kryukov 20-Jan-11 20:58pm    
I'm cleaning up my text just a bit, will appreciate your patience...
Provided my clarification asked by Donald is accepted (well, I don't see further questions from him), I want to proceed with some code.

I found that some other Inquirers ask questions I can answer in a very similar way, I decided to provide part of the solution in the form if some generic queue class for inter-thread communication.

Please see my miniature work in Tpis & Tricks:
Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

It covers two types of issues at the same time

1) How to work with fixed number of "permanent" application threads without idle run of any of them? This should show how to solve a problem of 100% CPU consumption (more exactly, running one thread without wait/sleep condition would typically consume 100% of one of CPU cores).

2) How to implement a technique of inter-thread Invoke similar to that used by System.Windows.Forms.Control.Invoke or System.Windows.Threading.Dispatcher.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 23-Jan-11 17:21pm    
When commenting this Answer, please comment the my Tips/Tricks work as well (referenced).
Thank you,
--SA
Espen Harlinn 24-Jan-11 13:55pm    
Nice work 5+
Hi Donald,

I think you should buy youself a copy of Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects (POSA2)[^], and The ACE Programmer's Guide: Practical Design Patterns for Network and Systems Programming[^]. The latter is C++ oriented, but it will show you how to build flexible and robust software.

The POSA books are considered among the most important works on software patterns, and you can think of a pattern as a proven recipe for building software that does what it's supposed to do.

ACE is a C++ library, and IMHO one of the finer examples of software engineering. ACE is an open source project lead by Douglas C. Schmidt[^]. Over the years several thousand developers has contributed to this framework. ACE (and TAO) shows how patterns can be used to create "real" high performance, robust and maintainable software.

Many of the POSA patterns are implemented in the .Net framework, and the books will help you decide on, and understand, which mechanisms are best suited to solve the problems you are working on.

The solution I outlined in How to execute high volume inserts and query the table simultaneously[^], Leverages .Net worker threads; which is, as Nishant Sivakumar mentioned, a suitable mechanism for solving your problem.

From what I can see from your code, it seems like you are working on some kind of trading system.

If it’s for real, as in money will change hands, you have a long journey ahead of you. If this is the case - I suggest you start with reading up on the Sarbanes–Oxley Act[^] and other legal matters.

Next thing to look at is probably the Financial Information eXchange (FIX) Protocol[^], a messaging standard developed specifically for the real-time electronic exchange of securities transactions. You'll find an implementation at http://www.quickfixengine.org/[^], it can be used with .Net.

At this point things might seem a bit overwhelming, you need some kind of data model to build upon, because the complexity of the problem is growing exponentially. Len Silverston[^] provides reference models with a proven track record.


Regards
Espen Harlinn
 
Share this answer
 
v3
Comments
Sergey Alexandrovich Kryukov 23-Jan-11 13:35pm    
That is very interesting answer - my 5.
I'm not sure OP would accept anything beyond C# though.
Espen Harlinn 23-Jan-11 16:41pm    
The POSA books goes into the "why" of things. I think the OP actually wants to understand things, so I hope he enjoys reading as much as I do. I think the POSA books are excellent, and you'll find that the .Net framework implements just about all of the patterns from the POSA2, or nearly so - different names though :)

ACE usually uses the same names - and playing around with them in this context may help to clarify the interaction between the patterns in a framework. Once you have some understanding of this, recognizing where and how things are done in .Net becomes easier – or maybe that’s just me and my sometimes convoluted journey to understanding.
Sergey Alexandrovich Kryukov 25-Jan-11 11:41am    
OP certainly wants to understand things, which is the only way to be productive.
Sergey Alexandrovich Kryukov 23-Jan-11 17:13pm    
Updated. Please see my other Answer and my new article in Tips & Tricks (referenced).

This time I put some code. Could be useful to answer other question (I already answered, but I need to update, because my code would make it much more clear).

Thank you,
--SA
Well on a dual-core (or dual proc) machine, if you have 2 threads doing tons of work, then yes, you will see 100% CPU usage. You've also increased the thread priority on one of your threads. That won't help much either. If your goal is run these long tasks in the background without disturbing the performance of the machine so that other apps can function normally, you probably need to use lower priority threads.

[Edit]
-----------

In your onQuote function, you have an infinite while loop. This is why your form is not responsive. The loop is executing in your UI thread. You can get around that by having another thread that will then spawn off these endless threads. This way your UI will remain responsive.

Once again if you have multiple threads that are created repeatedly in an infinite loop, your CPU will take up 100%. That's the way CPUs are designed anyway. If an app wants the CPU, it will be available.
 
Share this answer
 
v2
Comments
d.allen101 20-Jan-11 20:25pm    
Thanks for the suggestion to change the dataThread priority to normal but it's much more to it than just changing a threads priority. It's NO way that 100% of the CPU should be used for this process! Also the WinForm becomes unresponsive.
Nish Nishant 20-Jan-11 20:31pm    
Check my updated reply.

**edit - removed the sarcasm :-)
Manfred Rudolf Bihy 20-Jan-11 20:34pm    
Hey I'm still here! :)
Compensated. Mustn't nescessarily have been OP, but maybe he'll enlighten us about this issue.
Nish Nishant 20-Jan-11 20:35pm    
Thank you, Manfred.
Nish Nishant 20-Jan-11 20:36pm    
And yes, that's why I edited it, since you can never know who voted (you can only guess based on the status of the voter)!

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