替代Thread while while循环

时间:2017-07-10 08:52:02

标签: c# wpf multithreading sleep

在我的应用程序中,我有少量线程(5)执行以下方法:

private void ThreadMethod()
{
     while(true)
     {
          if(CurrentItem != null)
          {
               HandleCurrentItem();
          }
          Thread.Sleep(200);
     }
}

从我所看到的情况来看,这不是推荐的做法,但大多数论据都是因为你没有反应能力,你无法取消线程,或者时机不准确。这些对我来说都不是问题,但是我担心在此浪费太多的CPU资源。根据我在01:05:35看到的here,当您调用Sleep方法时,处理器将获得充分利用。

我的问题:

在我的方案中,这是一个不错的解决方案吗? 如果没有,怎么做得更好?

注意:我正在使用.Net Framework 4.0

注意2:这些线程位于类的不同实例中,因此CurrentItem是每个线程的不同对象。

4 个答案:

答案 0 :(得分:3)

当您想要在最后一次操作后200毫秒执行某些操作时,您也可以使用Timer而不是睡眠。这不会旋转锁定处理器。

var timer = new Timer(200);
timer.Elapsed += (sender, args) => 
{ 
    if(CurrentItem != null)
        HandleCurrentItem(); 
};
timer.AutoReset = true;
timer.Start();
  

.NET Framework类库包含四个名为Timer的类,每个类都提供不同的功能:

  • System.Timers.Timer,它会触发事件并定期在一个或多个事件接收器中执行代码。该类旨在用作多线程环境中的基于服务器或服务组件;它没有用户界面,在运行时不可见。
  • System.Threading.Timer,它定期在线程池线程上执行单个回调方法。回调方法是在实例化定时器时定义的,无法更改。与System.Timers.Timer类一样,此类旨在用作多线程环境中的基于服务器或服务组件;它没有用户界面,在运行时不可见。
  • System.Windows.Forms.Timer,一个Windows窗体组件,用于触发事件并定期在一个或多个事件接收器中执行代码。该组件没有用户界面,专为在单线程环境中使用而设计;它在UI线程上执行。
  • System.Web.UI.Timer,一个ASP.NET组件,定期执行异步或同步网页回发。

答案 1 :(得分:2)

您可以制作方法async并将其设为await

private async void ThreadMethod()
{
     while(true)
     {
         if(CurrentItem != null)
         {
             HandleCurrentItem();
         }
         await Task.Delay(200);
     }
}

这不会阻止线程

注意异步等待关键字只能使用.Net 4.0在visual studio 2012+上与Microsoft.Bcl.Async一起使用(您可以在nuget上获取此包)。

您也可以使用此代码段(信用到:Calvin Fisher):

new System.Threading.ManualResetEvent(false).WaitOne(1000);

答案 2 :(得分:1)

您可以使用Hangfire实现干净的实施。这将使您可以更好地控制您的任务,如果功能执行或失败,您也将获得反馈。

您可以创建这样的预定作业:

RecurringJob.AddOrUpdate(() => Console.WriteLine("Recurring!"),Cron.Daily);

您可以在文档中探索更多选项。

答案 3 :(得分:-1)

您可以使用AutoRestEvent

private void ThreadMethod()
{
    AutoResetEvent _restEvent = new AutoResetEvent(false);
    _restEvent.Reset();
    while(true)
    {
        if(CurrentItem != null)
        {
            HandleCurrentItem();
        }
        _restEvent.WaitOne(200);   // Set a timeout in ms.
    }
}