2013-08-25 144 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'来简化代码。 –