2012-08-22 80 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); 
}