2013-08-25 142 views
0
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 



namespace NewTask 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      NewTask.Combine taskcombine = new NewTask.Combine(); 
      ProfileClient profilesws = new ProfileClient(); 
      var profileRecords = profilesws.GetAllProfiles(); 
      foreach (var profile in profileRecords.ProfileRecords) 
      { 
       var testProfile = new NewTask.Profile(); 
       testProfile.Id = profile.Id; 
       testProfile.Name = profile.Name; 


       var result = taskcombine.TestProfile(testProfile); 

      } 


      profilesws.Close(); 
      taskcombine.Close(); 
     } 
    } 
} 

我想要一種方法來運行此異步。我想擊中這條路,一旦它將所有記錄都傳遞給我想讓它結束任務的結果。這將是一個CONSOL應用程序,一旦結果填充所需的記錄,我希望它異步關閉應用程序。異步運行控制檯任務

+1

你真的想異步嗎?或者你真的想找平行嗎?因爲如果它是異步的,在任務運行的同時還要完成其他工作? Taskcombine.TestProfile可以安全地從多個線程運行嗎?如果你沒有做任何事情,你爲什麼要返回結果? –

+0

這與你的問題有何不同:http://stackoverflow.com/questions/18388419/run-console-asynchronously-to-result-a-more-efficient-output? –

+0

我不希望它等到它經歷完整的循環。我希望它運行異步,一旦結果填充關閉應用程序,而不是等待其餘的。 – MohammedT

回答

1

如果TestProfileTestProfileAsync版本,返回任務的代碼將

class Program 
{ 
    static void Main(string[] args) 
    { 
     NewTask.Combine taskcombine = new NewTask.Combine(); 
     ProfileClient profilesws = new ProfileClient(); 
     var profileRecords = profilesws.GetAllProfiles(); 

     var tasks = new List<Task<ResultClass>>(); 

     foreach (var profile in profileRecords.ProfileRecords) 
     { 
      var testProfile = new NewTask.Profile(); 
      testProfile.Id = profile.Id; 
      testProfile.Name = profile.Name; 

      tasks.Add(taskcombine.TestProfileAsync(testProfile)) 
     } 

     int completedIndex = Task.WaitAny(tasks.ToArray()); 

     var result = tasks[completedIndex].Result; 

     profilesws.Close(); 
     taskcombine.Close(); 
    } 
} 

如果函數沒有一個異步的版本,你需要把它包在自己的任務。

tasks.Add(Task<ResultClass>.Factory.Start(() => taskcombine.TestProfile(testProfile))); 

這都假設taskcombine.TestProfile是線程安全的。如果它不是線程安全的,你需要更多地解釋什麼taskcombine.TestProfile做,如果你能做出它的多個實例

tasks.Add(Task<ResultClass>.Factory.Start(() => 
{ 
    NewTask.Combine taskcombine = new NewTask.Combine(); //Move the declaration inside the task so a new Combine gets created per task. 
    return taskcombine.TestProfile(testProfile); 
})); 

編輯:另外一個好辦法,你可以做的是使用一個cancellation token所以如果在某些任務甚至開始之前,你已經有了一個結果,他們根本不會開始。

首先,異步版本TestProfileAsync的有簽名的夢想解決方案Task<ResultClass> TestProfileAsync(NewTask.Profile a, CancllationToken token)

class Program 
{ 
    static void Main(string[] args) 
    { 
     NewTask.Combine taskcombine = new NewTask.Combine(); 
     ProfileClient profilesws = new ProfileClient(); 
     var profileRecords = profilesws.GetAllProfiles(); 

     var tasks = new List<Task<ResultClass>>(); 
     var cts = new CancellationTokenSource(); 
     var token = cts.Token;    

     foreach (var profile in profileRecords.ProfileRecords) 
     { 
      var testProfile = new NewTask.Profile(); 
      testProfile.Id = profile.Id; 
      testProfile.Name = profile.Name; 

      tasks.Add(taskcombine.TestProfileAsync(testProfile, token)) 
     } 

     int completedIndex = Task.WaitAny(tasks.ToArray()); 

     //This should stop any tasks before they even start. 
     cts.Cancel(); 

     var result = tasks[completedIndex].Result; 

     profilesws.Close(); 
     taskcombine.Close(); 
    } 
} 

如果你沒有獲得一個異步的版本,這裏是4.5版本的代碼與任務

class Program 
{ 
    static void Main(string[] args) 
    { 
     NewTask.Combine taskcombine = new NewTask.Combine(); 
     ProfileClient profilesws = new ProfileClient(); 
     var profileRecords = profilesws.GetAllProfiles(); 

     var tasks = new List<Task<ResultClass>>(); 
     var cts = new CancellationTokenSource(); 
     var token = cts.Token;    

     foreach (var profile in profileRecords.ProfileRecords) 
     { 
      var testProfile = new NewTask.Profile(); 
      testProfile.Id = profile.Id; 
      testProfile.Name = profile.Name; 

      //If the token is canceled before the task gets to start itself it should never start and go stright to the "Canceled" state. 
      tasks.Add(Task.Run(() => 
         { 
          token.ThrowIfCancellationRequested(); //In case the task started but we did get a result before the last 
          return taskcombine.TestProfile(testProfile); //Assumes "taskcombine.TestProfile(...)" is thread safe. 
         }, token)); 
     } 

     var result = Task.WhenAny(tasks).Result; 

     //This should stop any tasks that have not spun up yet from spinning up 
     cts.Cancel(); 

     profilesws.Close(); 
     taskcombine.Close(); 
    } 
} 
+0

所有這些代碼使用4.0類。如果您使用4.5,您可以執行像tasks.Add(Task.Run(()=> taskcombine.TestProfile(testProfile)));''和'Task.WhenAny(tasks).Result'來簡化代碼。 –