2012-08-22 132 views
2

我有这样的代码创建一个任务:如何暂停执行任务

Task.Factory.StartNew(() => 
         { 
          ExtractStuff(fileName); 
         }); 

有时候,我需要暂停几秒钟内ExtractStuff

是否确定使用常规的Thread.Sleep(1000)?还是有另一种方法来暂停正在运行的任务?

+0

当你说,是否可以使用Thread.Sleep(),你是什么意思? –

+0

某些其他线程是否需要暂停某些工作? –

+0

我的意思是它会暂停任务,或者它会暂停父线程。 – user1615362

回答

3

我相信这样做很好,但最好使用TaskCreationOptions.LongRunning

Task.Factory.StartNew(() => 
        { 
         ExtractStuff(fileName); 
        },TaskCreationOptions.LongRunning); 
+3

我不明白这是如何涉及到这个问题? –

+4

@James,这提示任务调度程序您的任务可能需要一段时间才能执行,因此它应该避免在Task中绑定一个有限的资源(如线程池)。这可能会产生一些额外开销(从分配新线程而不是使用池中的线程),但可能会阻止其他问题(多任务占用池并及时休眠,阻止其他任务启动)。你打算在你的任务中睡觉,你可能应该考虑自己长时间运行。 –

1

如果需要推迟ExtractStuff的执行,你可以在ThreadPool.RegisterWaitForSingleObject看看,与从未设置WaitHandle的结合。

private static WaitHandle NeverSet = new WaitHandle(); 
private void ExtractStuff(object state) 
{ 
    string filename = state as string; 
    .... 
} 

private void StartExtract(string filename); 
{ 
    ThreadPool.RegisterWaitForSingleObject(NeverSet, ExtractStuff, fileName, seconds * 1000, true); 
} 

希望这会帮助你在你的追求。

+0

不,我不需要延迟ExtractStuff的执行。我需要根据内部逻辑在中间暂停执行ExtractStuff。 – user1615362

4

Thread.Sleep会阻塞运行任务的线程(这并不理想),但只要没有运行大量数据,它可以是一个可以接受的折衷方案(低风险,性能不是很大的问题)并行的任务。 .NET 4.5对'async/await'和Task.Delay有一些改进,它会隐式设置基于计时器的延续(不需要阻塞正在运行的线程),但这在4.0中不是直接可用的。

你可以自己做同样的事情,像这样的东西(没有测试很多,所以请谨慎使用):

class Program 
{ 
    static void Main(string[] args) 
    { 
     var fullAction = RunActionsWithDelay(DoSomething, 2000, DoSomethingElse); 
     fullAction.Wait(); 
     Console.WriteLine("Done"); 
     Console.ReadLine(); 
    } 

    static Task RunActionsWithDelay(Action first, int delay, Action second) 
    { 
     var delayedCompletion = new TaskCompletionSource<object>(); 
     var task = Task.Factory.StartNew(DoSomething); 
     task.ContinueWith(t => 
     { 
      if (t.IsFaulted) 
      { 
       delayedCompletion.SetException(t.Exception); 
      } 
      else 
      { 
       Timer timer = null; 
       timer = new Timer(s => 
       { 
        try 
        { 
         DoSomethingElse(); 
         delayedCompletion.SetResult(null); 
        } 
        catch (Exception ex) 
        { 
         delayedCompletion.SetException(ex); 
        } 
        finally 
        { 
         timer.Dispose(); 
        } 
       }, null, delay, Timeout.Infinite);      
      } 

     }); 
     return delayedCompletion.Task; 
    } 

    static void DoSomething() 
    { 
     Console.WriteLine("Something"); 
    } 

    static void DoSomethingElse() 
    { 
     Console.WriteLine("Something Else"); 
    } 
} 

这是相当难看,但你可以封装比它上面好一点。它确实消除了“悬挂”线程,但是与设置延续相关的额外性能开销。如果你有很多并行任务正在运行,并且他们都需要引入延迟,我真的只是建议你这样做。

+0

你说Thread.Sleep会阻塞运行任务的线程,但是如果我使用LongRunning,是不是会导致只有任务被暂停而不是运行任务的线程? – user1615362

+0

+1,并感谢扩大我的答案,应该回到它。 –

+0

@ user1615362'Thread.Sleep()'总是阻塞当前线程。如果你使用'LongRunning',它不会是'ThreadPool'中的一个线程,但它仍然是一些线程,所以它仍然是浪费。 – svick

0

您可以使用Task.Delay(超时)并等待您的ExtractStuff方法。

private async string ExtractStuff(fileName) 
{ 
    // Your Code 
    await Task.Delay(timeout); 
}