2014-02-25 22 views
1

這裏的主要思想是從某處獲取一些數據,當它被提取時開始寫入數據,然後準備下一批要寫入的數據,同時等待先前的數據寫完成。c#等價於用某些參數重新啓動任務

我知道一個Task無法重新啓動或重新使用(也不應該),雖然我試圖找到一種方法,做這樣的事情:

//The "WriteTargetData" method should take the "data" variable 
//created in the loop below as a parameter 
//WriteData basically do a shedload of mongodb upserts in a separate thread, 
//it takes approx. 20-30 secs to run 
var task = new Task(() => WriteData(somedata)); 

//GetData also takes some time. 
foreach (var data in queries.Select(GetData)) 
{ 
    if (task.Status != TaskStatus.Running) 
    { 
     //start task with "data" as a parameter 
     //continue the loop to prepare the next batch of data to be written 
    } 
    else 
    { 
     //wait for task to be completed 
     //"restart" task 
     //continue the loop to prepare the next batch of data to be written 
    } 
} 

任何建議表示讚賞!謝謝。我不一定要使用Task,我只是覺得它可能是要走的路。

回答

1

這可能會過分簡化您的要求,但只是「等待」以前的任務爲您完成工作?您可以使用Task.WaitAnyTask.WaitAll等待以前的操作完成。

僞代碼:

// Method that makes calls to fetch and write data. 
    public async Task DoStuff() 
    { 
     Task currTask = null; 

     object somedata = await FetchData(); 

     while (somedata != null) 
     { 
      // Wait for previous task. 
      if (currTask != null) 
       Task.WaitAny(currTask); 

      currTask = WriteData(somedata); 

      somedata = await FetchData(); 
     } 
    } 

    // Whatever method fetches data. 
    public Task<object> FetchData() 
    { 
     var data = new object(); 

     return Task.FromResult(data); 
    } 

    // Whatever method writes data. 
    public Task WriteData(object somedata) 
    { 
     return Task.Factory.StartNew(() => { /* write data */}); 
    } 
+0

這實際上是我正在尋找的!謝謝。我只需要找到一種方法來保持應用程序使用的內存不會隨着'while'循環而上升。 – LaurentH

0

該任務類不旨在重新啓動。所以您需要創建一個新任務並使用相同的參數運行主體。接下來,我沒有看到它的主體中的WriteData函數開始的任務。這將屬性消除呼叫if (task.Status != TaskStatus.Running)有AFAIK只有類TaskThread其中任務只是一個行動的抽象,將與TaskScheduler計劃和執行在不同的線程(當我們在談論通用任務調度,一個當你打電話給TaskFactory.Scheduler時),並且線程數等於處理器內核的數量。

給你商業應用程序。你爲什麼要等待執行WriteData?將所有數據都彙集起來並提交給一個大寫的數據會不會更容易?

+0

雖然我不確定你的建議是什麼,但我不確定你的建議是什麼...... 我必須這樣做,因爲收集所有數據會消耗太多的RAM,它是一個非常大的數據集(大約22M mongo文件)。我必須將它分成更小的塊並分別處理這些塊。 – LaurentH

+0

但是,如果你使用這麼多的數據,我想你現在的方法不適合你的需求。您需要的是[限制併發性的任務計劃程序](http://msdn.microsoft.com/zh-cn/library/ee789351%28v=vs.110%29.aspx) – JPVenson

0

像?

 public void Do() 
     { 
      var task = StartTask(500); 
      var array = new[] {1000, 2000, 3000}; 

     foreach (var data in array) 
     { 
      if (task.IsCompleted) 
      { 
       task = StartTask(data); 
      } 
      else 
      { 
       task.Wait(); 
       task = StartTask(data); 
      } 
     } 
    } 

    private Task StartTask(int data) 
    { 
     var task = new Task(DoSmth, data); 
     task.Start(); 
     return task; 
    } 

    private void DoSmth(object time) 
    { 
     Thread.Sleep((int) time); 
    } 
0

您可以使用線程和AutoResetEvent。我在我的程序中有幾個不同線程的代碼:

這些是屬於主程序的變量聲明。

public AutoResetEvent StartTask = new AutoResetEvent(false); 
public bool IsStopping = false; 
public Thread RepeatingTaskThread; 

某處在您的初始化代碼:

RepeatingTaskThread = new Thread(new ThreadStart(RepeatingTaskProcessor)) { IsBackground = true; }; 
RepeatingTaskThread.Start(); 

然後運行重複任務將看起來像這樣的方法:

private void RepeatingTaskProcessor() { 
    // Keep looping until the program is going down. 
    while (!IsStopping) { 
     // Wait to receive notification that there's something to process. 
     StartTask.WaitOne(); 

     // Exit if the program is stopping now. 
     if (IsStopping) return; 

     // Execute your task 
     PerformTask(); 
    } 
} 

如果有幾個不同的任務要運行時,可以添加一個變量,用於指示要處理哪個變量並修改PerformTask中的邏輯以選擇要運行的邏輯。

我知道它不使用Task類,但有多種方法可以將貓皮膚&這將工作。

相關問題