2014-03-25 259 views
1

我有我在一個新的任務與WPF線程延遲

// get the dispatcher for the UI thread 
var uiDispatcher = Dispatcher.CurrentDispatcher; 
Task.Factory.StartNew(() => BackgroundThreadProc(uiDispatcher)); 

調用該方法BackgroundThreadProc()我需要幾秒鐘的延遲的方法。我用DispatcherTimer和task.delay函數嘗試了它,但它不起作用。唯一的工作是System.Threading.Thread.Sleep(1),但我認爲Thread.Sleep()功能不是最好的解決方案。

這是我的函數:

public void BackgroundThreadProc(Dispatcher uiDispatcher) 
{ 
    for (var i = 0; i < 100; i++) 
    { 
     var task = Task.Delay(1000).ContinueWith(t => 
     { 
      // create object 
      var animal = new Animal { Name = "test" + i }; 
      uiDispatcher.Invoke(new Action(() => log(animal))); 
     }); 
    } 
} 

當我發現了,因爲DispatcherTimer在UI線程中運行它沒有工作。我如何才能在UI線程之外的其他線程中實現延遲?

更新:

現在我與定時器試了一下:

public void BackgroundThreadProc(Dispatcher uiDispatcher) 
    { 
     for (var i = 0; i < 100; i++) 
     { 
      var _delayTimer = new System.Timers.Timer(); 
      _delayTimer.Interval = 1000; 
      //_delayTimer.Enabled = true; 
      _delayTimer.Elapsed += delegate 
      { 
       var animal = new Animal { Name = "test" + i }; 
       uiDispatcher.Invoke(new Action(() => log(animal))); 
       _delayTimer.Stop(); 
      }; 
      _delayTimer.Start(); 
     } 
    } 

回答

4

使用Task.Delay到asynchrnoously引入延遲:

var task = Task.Delay(1000) 
    .ContinueWith(t => BackgroundThreadProc()); 
+0

Hy,謝謝ypur的回答。我試着用你的例子,但問題是延遲結束後,它一直寫「test100」到我的輸出,因爲在延遲後,for循環已經完成,但我希望在每個I ++之後延遲。我將BackgroundThreadProc()添加到了我的文章中。 – user2644964

+0

@ user2644964聽起來就像你只是想要一個'計時器'。你可以使用TPL來做到這一點,但它的工作方式比它的價值更大。只需使用一個「計時器」。 – Servy

+0

Hy,帶計時器,你的意思是System.Timers.Timer?我嘗試了一個例子,並更新了「更新」下的主要帖子,你可以找到我嘗試過的功能。我最終遇到同樣的問題,它只在輸出上寫了一個houndret時間「test100」。 – user2644964

1

你限制在C#4.0?我假設你沒有,因爲Task.Delay將不可用。

因此,請BackgroundThreadProc一個async方法和使用await裏面:

// get the dispatcher for the UI thread 
var uiDispatcher = Dispatcher.CurrentDispatcher; 
var task = BackgroundThreadProc(uiDispatcher)); 

// ... 

public async Task BackgroundThreadProc(Dispatcher uiDispatcher) 
{ 
    for (var i = 0; i < 100; i++) 
    { 
     await Task.Delay(1000).ConfigureAwait(false); 

     // create object 
     var animal = new Animal { Name = "test" + i }; 
     uiDispatcher.Invoke(new Action(() => log(animal))); 
    } 
} 

你真的不需要Task.Factory.StartNew這裏,執行將await Task.Delay後繼續線程池。

顯然,你只是從這個BackgroundThreadProc更新UI。如果是這樣的話,只是刪除ConfigureAwait(false)並且不使用uiDispatcher.Invoke

public async Task BackgroundThreadProc() 
{ 
    for (var i = 0; i < 100; i++) 
    { 
     await Task.Delay(1000); 

     // create object 
     var animal = new Animal { Name = "test" + i }; 
     log(animal); 
    } 
} 

這個循環將異步的WPF UI線程上執行。

否則,如果你這樣做Task.Delay之前有任何其他CPU密集型的工作,那麼你可能需要Task.Factory.StartNew避免凍結UI(注Unwrap):

var task = Task.Factory.StartNew(() => 
    BackgroundThreadProc(uiDispatcher)).Unwrap(); 

您還可以使用Task.Run,這自動解開內部任務:

var task = Task.Run(() => BackgroundThreadProc(uiDispatcher));