2017-05-25 77 views
0

我正在使用此代码来执行任务恢复和暂停。我需要暂停,因为doSomething();方法不会每次都工作,例如当数据来自web api时。所以CPU不会疲劳。我在很多项目中都使用这个技术。但我不确定这是可靠的还是最好的方法。我可以问你的想法吗?对于任务暂停和恢复我可以使用ManualResetEventSlim吗?

static ManualResetEventSlim mre = new ManualResetEventSlim(false); 
    static void Main(string[] args) 
    { 

     mre.Set(); 
     Task.Factory.StartNew(() => 
     { 
      while (true) 
      { 
       mre.Wait(); 
       doSomething(); 
      } 

     }); 

     mre.Reset(); 
     Console.WriteLine("Task Paused"); 
     Console.WriteLine("Task Will Resume After 1 Second"); 
     Thread.Sleep(1000);//To simulate, waiting data from Web Api etc. for doSomething(); 
     mre.Set(); 

     Console.Read(); 
    } 
+0

这是一个代码审查问题,你应该问一下https://codereview.stackexchange.com/ –

+1

你在'mre.mait()'和'mre.Reset()'之间有竞争条件。设置()'。有可能mre.Wait()的执行速度比重置信号的速度快,因此你的'doSomething()'方法在第一个Thread.Sleep()之前触发。如果在mre.Reset()之前添加Thread.Sleep(10),则可以轻松地进行仿真。 – Szer

+3

如果你认为你需要“暂停”一项任务,那么你做错了什么。在这种情况下,您将任务视为线程。不是。你*不需要那个无限循环。还有其他方法可以执行不需要浪费线程的任务 –

回答

1

您可以使用SemaphoreSlim

SemaphoreSlim _semaphore; 
static void Main(string[] args) 
    { 
     _semaphore = new SemaphoreSlim(0); 

     Task.Factory.StartNew(() => 
     { 
      while (true) 
      { 
       _semaphore.Wait(); 
       doSomething(); 
      } 

     }); 

     _semaphore.Release(); 
     Console.WriteLine("Task Paused"); 
     Console.WriteLine("Task Will Resume After 1 Second"); 
     Thread.Sleep(1000);//To simulate, waiting data from Web Api etc. for doSomething();  
     _semaphore.Release(); 
     Console.Read(); 
    } 

信号灯会一直过渡到 内核;相比之下,与ManualResetEventSlim,SemaphoreSlim已被设计为留在用户模式作为 尽量,典型地导致对过程内螺纹通信更好的性能和可扩展性。
SemaphoreSlim还 提供CURRENTCOUNT属性它可以访问该计数值时,通常仅用于调试 目的。

注意事项:

与ManualResetEventSlim,访问的 底层内核对象SemaphoreSlim的AvailableWaitHandle属性力量的初始化。这增加了后续等待和释放调用的开销,现在需要 维持WaitHandle的状态。

请注意,此属性的名称AvailableWaitHandle与 ManualResetEventSlim上的WaitHandle属性的名称不同。这是由于返回的WaitHandle中的功能差异。等待一个ManualResetEvent的 或ManualResetEventSlim不会改变事件的信号状态。然而,等待信号量的 可能会改变信号量,因为它可以减少信号量的内部计数。这样, 的AvailableWaitHandle属性返回WaitHandle的,仅仅表示高可能性有计数 可用于在SemaphoreSlim消耗;要实际获得对关联的共享资源的访问权,然而,必须直接在SemaphoreSlim上等待。

这一切意味着可能与信号量一定的同步操作是不可能与 SemaphoreSlim。例如,与信号量,能够使用WaitHandle.WaitAll的以原子方式获取从多个信号量 资源;该功能在SemaphoreSlim中不存在。

+0

_semaphore.Release()将被调用,只要真是假=>我想这将永远不会发生 –

+1

而问题是关于暂停任务执行,而不是暂停主执行 –

+0

@SirRufo - 你是对的。我改变了我的答案。 –