2017-03-22 33 views
1

我想知道如何檢查c#中異步任務的狀態。 我有一個保存方法來保存用戶,我想運行一個後臺任務來保存後更新它們。如何檢查c中的任務狀態#

我在框架4.0,這裏是我的代碼開始任務

System.Threading.Tasks.Task task = null; 
task = System.Threading.Tasks.Task.Factory.StartNew(() => 
     {     
      beginTask(); 
     }); 

我的問題是任務需要一段時間才能結束(近7分鐘),所以如果有人做一些用戶保存時,任務運行多次,所以如果函數beginTask()已經在運行,以避免運行大量的後臺任務,我想在運行任務之前檢查它。

感謝

+0

你的任務結束會發生什麼?你的任務對象存儲在某個地方在運行前檢查它嗎? –

+0

是的,BeginTask()逐個保存用戶來更新一個字段。所以需要很長時間,因爲我需要等5秒來更新用戶,因爲我打電話給API,我不能每5秒請求一次以上。這就是爲什麼我要檢查beginTask()是否已經在運行,以避免在前一次調用運行時發生兩次或多次保存時執行它 –

+1

如何在命令正在進行時禁用UI按鈕? –

回答

4

我想我找到了更好的解決方案。檢查它是否適合你。

public class TaskDemo 
{ 
    private static AutoResetEvent autoReset = new AutoResetEvent(true); 

    Action beginTask =() => 
    { 
     Console.WriteLine("Method start"); 
     Thread.Sleep(2000); 
    }; 

    public void RunTask() 
    { 
     Task myTask = Task.Run(() => 
      { 
       autoReset.WaitOne(); 
       beginTask(); 
      }).ContinueWith(t => autoReset.Set()); 
    } 
} 

,簡單的控制檯應用程序測試:

static void Main(string[] args) 
    { 
     TaskDemo td = new TaskDemo(); 
     // Simulation multiple requests 
     Thread.Sleep(1000); 
     td.RunTask(); 
     Thread.Sleep(1000); 
     td.RunTask(); 
     Thread.Sleep(1000); 
     td.RunTask(); 
     Thread.Sleep(1000); 
     td.RunTask(); 
     Thread.Sleep(1000); 
     td.RunTask(); 
     Thread.Sleep(1000); 
     td.RunTask(); 
    } 

線索是使用AutoResetEvent信號任務狀態和

Task myTask = Task.Run(() => 
      { 
       autoReset.WaitOne(); 
       beginTask(); 
      }).ContinueWith(t => autoReset.Set()); 

運行過程中和完成後改變其狀態(ContinueWith(t => autoReset.Set()) 。

+0

它很好,謝謝! –

+0

應該避免'StartNew',這不應該用class字段來完成,它甚至不標記爲volatile,這也是危險的。你需要在這裏使用自動重置事件 – VMAtm

+0

爲什麼? Task.Run會更好嗎? – daniell89

2

也許嘗試做這種way- 初始化你的任務目標:

Task task = new Task(begintask); 

並添加新的方法來運行它,例如:

public void StartTask(Task t) 
{ 
    if (t.Status == TaskStatus.Running) 
     return; 
    else 
     t.Start(); 
} 

當然你可以根據任務狀態添加更多條件。

+0

不錯的代碼,但問題是每次我會保存用戶,它會創建一個新的任務狀態「創建」,所以我不能測試是以前的BeginTask()仍在運行或不 –

+0

你真的需要創建新的tsks?也許只是嘗試將任務添加爲私有字段,然後爲其分配合適的方法並啓動它(在我的代碼中使用StartTask方法)。 – daniell89

+0

不,我不需要,但我如何分配我的類屬性,而不使用「新任務(beginTask());」 ?我有一個空引用錯誤,因爲我的財產從來沒有instanciate –

1

每個Task對象有一個Task.StatusTaskStatus類型的屬性,如果您已經有任務對象可以查詢它。它會告訴你任務是否正在運行,已完成,取消等。

如果您想檢查任何任務是否正在運行特定的功能塊,可能會更困難。一個可能的建議是保持一個任務變量全局可訪問的出於這個原因,任何時候他們試圖運行代碼所做的功能:

檢查全局,看看是否正在運行。

如果創建一個新的任務來運行它,並把它分配給全局變量

否則執行任何操作,你想做的事,如果它已經在運行(等待它也許結束?)

這聽起來像你是一個誤解任務和b)需要看看你的解決方案設計。

任務是表示要完成的工作的對象。任務不是BeginTask方法本身。 BeginTask方法或多或少只是一組要執行的指令。它沒有任何狀態。執行這些指令的單個任務確實有一個可以查詢的狀態。

如果你想這樣做,每個用戶只能運行一個任務,你只需要在某處全局存儲每個用戶的任務集合(例如用密鑰爲用戶的字典)。

理想情況下,這將創建並存儲在包含此應用程序功能部分的某種控制類中,或存儲在外部程序中(如果它是一個)。

爲了引用您對「我需要避免在每次保存用戶時創建新任務」的評論,爲此您必須修改該特定代碼以檢查任何存儲狀態運行任務。所以在上面我的想法中,你會改變這個功能來檢查一個Task是否存在於你已經開始的任務字典中保存的用戶,如果有,請檢查它的狀態。

如果您不確定,請在評論中繼續提問。也許如果你提供了更多關於這個系統的信息,那麼結構就會更好。

希望有所幫助。

+0

是的,但我在一個班,我需要避免每次我保存我的用戶創建一個新的任務。 BeginTask()只有在不處於「正在運行」狀態時才必須執行。每次我保存我的用戶,它創建一個新的任務狀態「創建」,所以我不能檢查beginTask()已經運行,由於以前的用戶保存 –

+0

@VincentDucroquet我已經更新了我的答案並回復了您的評論,它本身就是一個評論太久了。如果我誤解了某些內容,請繼續詢問我。 –

1

您可以使用屬性Task.IsCompletedTaskStatus

,順便試試這個方法Task.ContinueWith 我認爲使用Task.ContinueWith的調查是多任務的解決方案更好的辦法。

見下面的例子說明哪些建議我用Task.ContinueWith:

System.Threading.Tasks.Task task = null; 
     if (task==null) 
     { 
      task = Task.Factory.StartNew(() => 
      { 
       beginTask(); 

      }); 
      return; 
     } 

     if (task.Status == TaskStatus.Running) 
     { 
      task.ContinueWith((x) => 
      { 
       beginTask(); 

      }); 
     }else 
     { 
      task = Task.Factory.StartNew(() => 
      { 
       beginTask(); 

      }); 

     } 

此實現可以解決像潛在的問題的範圍:

  • 如何保持先前的任務
  • 當應系統啓動前 任務,
+0

不錯的代碼,但我在一個類(用戶類),每次我保存用戶它創建一個新的任務,這是我的問題。如果beginTask()當前正在運行,那麼需要的是一種檢查線程的方法。如果我可以檢查,我可以阻止另一個beginTask()執行 –

+0

你的意思是:檢查beginTask方法內最後一個任務狀態的方法,對吧? –