2

有两个流,第一个显示进程表,而第二个将它们视为计数并显示。最初是为第一个启动,然后是第二个:

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

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

4

5 回答 5

6

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

您还可以使用任务并行库的方式一个接一个地运行任务。

Task.Factory.StartNew(() => tmh1.FillTable()).ContinueWith(() => tmh1.GetGeneralInfo(), TaskScheduler.FromCurrentSynchronizationContext());
于 2012-05-16T12:58:33.460 回答
4

我会使用任务。例如:

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

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

Thread t1 = new Thread(()=>{tmh1.FillTable; tmh1.GetGeneralInfo();});
t1.Start();
于 2012-05-16T13:02:49.437 回答
3

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

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

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

        Console.ReadLine();

如果你想手动创建线程,你应该阅读信号结构

于 2012-05-16T13:03:26.927 回答
0

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

于 2012-05-16T12:59:24.577 回答
0

仅作为您发布的代码我不得不说在这里使用线程是没有意义的。我猜它的内容比你介绍的要多。也许您精简了代码以制作更小的帖子?

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

不过,还有其他技术可以使用。一种常见的方法是使用生产者-消费者模式。这在课堂上很容易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());
    }
}
于 2012-05-16T13:40:40.827 回答