Creative
Creative

Reputation: 307

How to make the threads run in the correct order

There are two streams, the first displays a table of processes, while the second considers them to count and displays. Initially launched for the first, then the second:

Thread t1 = new Thread(tmh1.FillTable);
Thread t2 = new Thread(tmh1.GetGeneralInfo);
t1.Start();
t2.Start();

Here are the methods that run in threads:

public void FillTable()
{
    while (true)
    {
         lock (lockObj)
         {
            arr.Clear();
            arr.AddRange(Process.GetProcesses());
            TableFormatter.Line();
            TableFormatter.Row("Name", "ID", "threads quantity", "Start time");
            TableFormatter.Line();
          }
          Thread.Sleep(interval);
      }
}
public void GetGeneralInfo()
{
    while (true)
    {
        lock (lockObj)
        {
           Console.WriteLine(arr.Count.ToString());
        }
    Thread.Sleep(interval);
    }
}

and the result:

0
-----------------------------------------------------------------------------
|     Name     |         ID       |  threads quantity|  Start time          |
-----------------------------------------------------------------------------

but should be the follow:

-----------------------------------------------------------------------------
|     Name     |         ID       |  threads quantity|  Start time          |
-----------------------------------------------------------------------------
**68**

How to make the treads run in the correct order?

Upvotes: 2

Views: 6767

Answers (5)

Brian Gideon
Brian Gideon

Reputation: 48949

Going only be the code you posted I have to say that the use of threads is pointless here. I am guessing there is more to it than what you presented. Perhaps you trimmed your code down to make for a smaller post?

Anyway, the solution which requires the least amount of tweaking and refactoring is to use Monitor.Pulse and Monitor.Wait.

public void FillTable()
{
    while (true)
    {
         Thread.Sleep(interval);
         lock (lockObj)
         {
            arr.Clear();
            arr.AddRange(Process.GetProcesses());
            TableFormatter.Line();
            TableFormatter.Row("Name", "ID", "threads quantity", "Start time");
            TableFormatter.Line();
            Monitor.Pulse(lockObj);
          }
      }
}

public void GetGeneralInfo()
{
    while (true)
    {
        lock (lockObj)
        {
           Monitor.Wait(lockObj);
           Console.WriteLine(arr.Count.ToString());
        }
    }
}

There are other techniques that can be used though. One common approach is to use the producer-consumer pattern. This is pretty easy with the BlockingCollection class.

private BlockingCollection<Process[]> queue = new BlockingCollection<Process[]>();

public void FillTable()
{
    while (true)
    {
         Thread.Sleep(interval);
         queue.Add(Process.GetProcesses());
    }
}

public void GetGeneralInfo()
{
    while (true)
    {
        Process[] processes = queue.Take();
        Console.WriteLine(processes.Length.ToString());
    }
}

Upvotes: 0

Thorsten Dittmar
Thorsten Dittmar

Reputation: 56697

Threads are supposed to run in parallel. If you want the task the second thread performs to be executed when the first thread is done, simply make the first thread execute the second task as well.

You could also use the means of the Task Parallel Library to run Tasks one after the other.

Task.Factory.StartNew(() => tmh1.FillTable()).ContinueWith(() => tmh1.GetGeneralInfo(), TaskScheduler.FromCurrentSynchronizationContext());

Upvotes: 6

RichardOD
RichardOD

Reputation: 29157

This code is very odd and it is difficult to determine why you want to create 2 threads that run after each other.

Assuming that the desired effect is running two things at different times on a different thread, the simplest way to do it, assuming you can use C# 4 is to utilise the Task Parallel Library. An example of which is as follows:

        Task.Factory
            .StartNew(() => Console.WriteLine("This is the first"))
            .ContinueWith(t => Console.WriteLine("This is the second"));

        Console.ReadLine();

If you want to create threads manually you should read up on the signalling constructs

Upvotes: 3

Peter Ritchie
Peter Ritchie

Reputation: 35881

I would use Task. For example:

Task.Factory.StartNew(tmh1.FillTable).ContinueWith(tmh1.GetGeneralInfo)

Although, it's not clear why you'd want two threads anyway. The following should also work:

Thread t1 = new Thread(()=>{tmh1.FillTable; tmh1.GetGeneralInfo();});
t1.Start();

Upvotes: 4

Waqar
Waqar

Reputation: 2591

You can use signaling using Reset Events (See AutoResetEvent or ManualResetEvent in C#). But calling for wait signal in a lock can be dangerous (e.g. dead lock)

Upvotes: 0

Related Questions