c#:什么是线程轮询?

时间:2010-10-03 12:26:42

标签: c# .net multithreading

当一个人说你的线程解决方案没有被允许时,这是什么意思,因为它是浪费的,它有延迟,而且是非确定性的。线程不应该使用轮询来互相发出信号。

修改

根据您到目前为止的答案,我认为下面的线程实现(取自:http://www.albahari.com/threading/part2.aspx#_AutoResetEvent)不使用轮询。如果我错了,请纠正我。

using System;
using System.Threading;
using System.Collections.Generic;

class ProducerConsumerQueue : IDisposable {
  EventWaitHandle _wh = new AutoResetEvent (false);
  Thread _worker;
  readonly object _locker = new object();
  Queue<string> _tasks = new Queue<string>();

  public ProducerConsumerQueue() (
    _worker = new Thread (Work);
    _worker.Start();
  }

  public void EnqueueTask (string task) (
    lock (_locker) _tasks.Enqueue (task);
    _wh.Set();
  }

  public void Dispose() (
    EnqueueTask (null);     // Signal the consumer to exit.
    _worker.Join();         // Wait for the consumer's thread to finish.
    _wh.Close();            // Release any OS resources.
  }

  void Work() (
    while (true)
    {
      string task = null;
      lock (_locker)
        if (_tasks.Count > 0)
        {
          task = _tasks.Dequeue();
          if (task == null) return;
        }
      if (task != null)
      {
        Console.WriteLine ("Performing task: " + task);
        Thread.Sleep (1000);  // simulate work...
      }
      else
        _wh.WaitOne();         // No more tasks - wait for a signal
    }
  }
}

4 个答案:

答案 0 :(得分:10)

您的问题非常清楚,但通常“轮询”是指定期检查条件或对值进行抽样。例如:

while (true)
{
    Task task = GetNextTask();
    if (task != null)
    {
         task.Execute();
    }
    else
    {
         Thread.Sleep(5000); // Avoid tight-looping
    }
}

只是睡觉是一种相对低效的方法 - 如果有一些协调,那么线程可以在有趣的事情发生时立即醒来,例如通过Monitor.Wait / PulseManual / AutoResetEvent ...但根据具体情况,并非总是可行。

在某些情况下,您可能不希望线程真正睡眠 - 您可能希望它可用于其他工作。例如,您可以使用某种Timer来定期轮询邮箱以查看是否有任何传入邮件 - 但是当它不检查时您不需要该线程实际处于休眠状态;它可以被另一个线程池任务重用。

答案 1 :(得分:1)

你去:查看这个网站:

http://msdn.microsoft.com/en-us/library/dsw9f9ts%28VS.71%29.aspx

同步技术

有两种同步,轮询和使用同步对象的方法。轮询重复检查循环内异步调用的状态。轮询是管理线程的最有效方法,因为它通过反复检查各种线程属性的状态来浪费资源。

例如,轮询时可以使用IsAlive属性来查看线程是否已退出。请谨慎使用此属性,因为活动的线程不一定在运行。您可以使用线程的ThreadState属性来获取有关线程状态的更多详细信息。由于线程在任何给定时间都可以处于多个状态,因此存储在ThreadState中的值可以是System.Threading.Threadstate枚举中值的组合。因此,在轮询时应仔细检查所有相关的线程状态。例如,如果线程的状态指示它不是Running,则可以完成。另一方面,它可能会暂停或睡眠。 等待线程完成

Thread.Join方法可用于在开始另一个任务之前确定线程是否已完成。 Join方法等待一个特定的时间让线程结束。如果线程在超时之前结束,则Join返回True;否则返回False。有关Join的信息,请参阅Thread.Join方法

轮询牺牲了多线程的许多优点,以换取对线程运行顺序的控制。因为效率太低,一般不推荐轮询。更有效的方法是使用Join方法来控制线程。 Join会导致调用过程等待一个线程完成,或者直到调用超时(如果指定了超时)。名称join是基于创建新线程是执行路径中的fork的想法。您可以使用Join将单独的执行路径再次合并到单个线程中

应该明确一点:加入是同步或阻止呼叫。一旦调用了Join或等待句柄的wait方法,调用过程就会停止并等待线程发出信号表明它已完成。 复制

Sub JoinThreads()
   Dim Thread1 As New System.Threading.Thread(AddressOf SomeTask)
   Thread1.Start()
   Thread1.Join()      ' Wait for the thread to finish.
   MsgBox("Thread is done")
End Sub

这些控制线程的简单方法(在管理少量线程时很有用)很难用于大型项目。下一节将讨论可用于同步线程的一些高级技术。

希望这有帮助。

<强> PK

答案 2 :(得分:1)

轮询可用于引用.NET用于委托执行的四种异步模式。

这4种类型(我从这个解释良好的answer中得到了这些描述):

  1. 轮询:等待IAsyncResult.Completed为真的循环
  2. 我会打电话给你
  3. 你叫我
  4. 我不在乎会发生什么(火灾和忘记)
  5. 因此,对于 1

    的示例
    Action<IAsyncResult> myAction = (IAsyncResult ar) =>
    {
        // Send Nigerian Prince emails
        Console.WriteLine("Starting task");
        Thread.Sleep(2000);
    
        // Finished
        Console.WriteLine("Finished task");
    
    };
    
    IAsyncResult result = myAction.BeginInvoke(null,null,null);
    while (!result.IsCompleted)
    {
        // Do something while you wait
        Console.WriteLine("I'm waiting...");
    }
    

    还有其他的投票方式,但总的来说它意味着“我还在那里”,“我还在那里”,“我还在那里”

答案 3 :(得分:1)

  

当一个人拒绝时,这是什么意思   恭维时允许进行投票   你的线程解决方案,因为它   浪费,它有延迟,它是   非确定性。线程不应该   使用轮询互相发出信号。

我必须看到这个陈述的背景,无论是哪种方式都表达了对它的意见。 然而,按原样,它显然是错误的。轮询是一种非常常见且非常被接受的信令线程策略。

几乎所有无锁线程信令策略都以某种形式使用轮询。这一点在这些策略通常如何在一个循环中旋转直到满足某个条件时就很清楚了。

最常用的情况是发信号通知工作线程是时候终止了。工作线程将定期在安全点轮询bool标志,以查看是否请求关闭。

private volatile bool shutdownRequested;

void WorkerThread()
{
  while (true)
  {
    // Do some work here.

    // This is a safe point so see if a shutdown was requested.
    if (shutdownRequested) break;

   // Do some more work here.
  }
}