如果TestProfile
有一个TestProfileAsync
返回任务的版本,您的代码将是
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);
}));
编辑:您可以做的另一项调整是使用取消令牌,因此如果您在某些任务开始之前已经有结果,它们根本不会开始。
首先,使用具有签名的异步版本的 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();
}
}