如何使线程以正确的顺序运行

时间:2012-05-16 12:53:53

标签: c# multithreading locking

有两个流,第一个显示进程表,第二个流则考虑计数和显示。最初是为第一个推出,然后是第二个:

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

以下是在线程中运行的方法:

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);
    }
}

结果:

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

但应该如下:

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

如何使踏板以正确的顺序运行?

5 个答案:

答案 0 :(得分:6)

线程应该并行运行。如果你想在第一个线程完成时执行第二个线程执行的任务,只需让第一个线程也执行第二个任务。

您也可以使用Task Parallel Library的方法一个接一个地运行任务。

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

答案 1 :(得分:4)

我会使用Task。例如:

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

虽然,目前尚不清楚为什么你还想要两个线程。以下内容也应该有效:

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

答案 2 :(得分:3)

这段代码很奇怪,很难确定你为什么要创建两个相继运行的线程。

假设期望的效果是在不同的线程上在不同的时间运行两件事,最简单的方法是假设您可以使用C#4来使用任务并行库。其中一个例子如下:

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

        Console.ReadLine();

如果您想手动创建线程,请阅读signalling constructs

答案 3 :(得分:0)

您可以使用重置事件使用信令(请参阅C#中的AutoResetEvent或ManualResetEvent)。但是在锁中调用等待信号可能很危险(例如死锁)

答案 4 :(得分:0)

只是你发布的代码我必须说线程的使用在这里毫无意义。我猜它还有比你提出的更多。也许你把你的代码缩减到一个较小的帖子?

无论如何,需要进行最少量调整和重构的解决方案是使用Monitor.PulseMonitor.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());
        }
    }
}

可以使用其他技术。一种常见的方法是使用生产者 - 消费者模式。使用BlockingCollection类非常简单。

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());
    }
}