推迟任务执行
Deferring tasks execution
我正在玩 Tasks,我想推迟执行任务。
我有一个这样的示例方法:
private async Task<bool> DoSomething(string name, int delayInSeconds)
{
Debug.WriteLine($"Inside task named: {name}");
await Task.Delay(TimeSpan.FromSeconds(delayInSeconds));
Debug.WriteLine($"Finishing task named: {name}");
return true;
}
我想先创建几个任务,然后执行一些工作,然后 运行 这些任务。由于行 Task<bool> myTask = DoSomething("Name", 4);
立即触发任务,我想到了这样的事情:
string[] taskNames = new string[2];
Task<Task<bool>>[] myTasks = new Task<Task<bool>>[2];
myTasks[0] = new Task<Task<bool>>(async () => await DoSomething(taskNames[0], taskNames[0].Length));
myTasks[1] = new Task<Task<bool>>(async () => await DoSomething(taskNames[1], taskNames[1].Length));
// I think I can declare it also like this, but this will create tasks later
//IEnumerable<Task<Task<bool>>> myTasks = taskNames.Select(x => new Task<Task<bool>>(async () => await DoSomething(x, x.Length)));
taskNames[0] = "First";
taskNames[1] = "Second";
Debug.WriteLine($"Tasks created");
var results = await Task.WhenAll(myTasks.Select(x => { x.Start(); return x.Unwrap(); }));
Debug.WriteLine($"Finishing: {results.Select(x => x.ToString()).Aggregate((a,b) => a + "," + b) }");
这可以用不同的方式完成吗,不包装任务?
您可以只使用 Task
生成委托来稍微简化一下:
string[] taskNames = new string[2];
Func<Task<bool>>[] myTasks = new Func<Task<bool>>[2];
myTasks[0] = new Func<Task<bool>>(async () => await DoSomething(taskNames[0], taskNames[0].Length));
myTasks[1] = new Func<Task<bool>>(() => DoSomething(taskNames[1], taskNames[1].Length)); // Shorter version, near-identical functionally.
// I think I can declare it also like this, but this will create tasks later
//IEnumerable<Task<Task<bool>>> myTasks = taskNames.Select(x => new Task<Task<bool>>(async () => await DoSomething(x, x.Length)));
taskNames[0] = "First";
taskNames[1] = "Second";
Debug.WriteLine($"Tasks created");
var results = await Task.WhenAll(myTasks.Select(x => x()));
Debug.WriteLine($"Finishing: {results.Select(x => x.ToString()).Aggregate((a, b) => a + "," + b) }");
警告:当您调用这些委托时,DoSomething
将同步执行到第一个 await
,因此行为相似,但 完全相同。
或者,您基于 IEnumerable
的解决方案也可以正常工作。只需在启动时编写迭代器方法和 yield return
任务。
就我个人而言,我会这样做:
string[] taskNames = new string[2];
taskNames[0] = "First";
taskNames[1] = "Second";
var results = await Task.WhenAll(taskNames.Select(n => DoSomething(n, n.Length)));
Debug.WriteLine($"Finishing: {results.Select(x => x.ToString()).Aggregate((a, b) => a + "," + b) }");
你的例子中不只是 "creating a Task
"。您正在调用一种方法 DoSomething
,即 returns 和 Task
。假设这些是 async
方法,Task
创建和启动发生在编译器生成代码的幕后。
此问题的解决方案很简单:在您准备好方法之前不要调用该方法 运行。想象一下您要求的行为在任何其他情况下会有多混乱。
我正在玩 Tasks,我想推迟执行任务。
我有一个这样的示例方法:
private async Task<bool> DoSomething(string name, int delayInSeconds)
{
Debug.WriteLine($"Inside task named: {name}");
await Task.Delay(TimeSpan.FromSeconds(delayInSeconds));
Debug.WriteLine($"Finishing task named: {name}");
return true;
}
我想先创建几个任务,然后执行一些工作,然后 运行 这些任务。由于行 Task<bool> myTask = DoSomething("Name", 4);
立即触发任务,我想到了这样的事情:
string[] taskNames = new string[2];
Task<Task<bool>>[] myTasks = new Task<Task<bool>>[2];
myTasks[0] = new Task<Task<bool>>(async () => await DoSomething(taskNames[0], taskNames[0].Length));
myTasks[1] = new Task<Task<bool>>(async () => await DoSomething(taskNames[1], taskNames[1].Length));
// I think I can declare it also like this, but this will create tasks later
//IEnumerable<Task<Task<bool>>> myTasks = taskNames.Select(x => new Task<Task<bool>>(async () => await DoSomething(x, x.Length)));
taskNames[0] = "First";
taskNames[1] = "Second";
Debug.WriteLine($"Tasks created");
var results = await Task.WhenAll(myTasks.Select(x => { x.Start(); return x.Unwrap(); }));
Debug.WriteLine($"Finishing: {results.Select(x => x.ToString()).Aggregate((a,b) => a + "," + b) }");
这可以用不同的方式完成吗,不包装任务?
您可以只使用 Task
生成委托来稍微简化一下:
string[] taskNames = new string[2];
Func<Task<bool>>[] myTasks = new Func<Task<bool>>[2];
myTasks[0] = new Func<Task<bool>>(async () => await DoSomething(taskNames[0], taskNames[0].Length));
myTasks[1] = new Func<Task<bool>>(() => DoSomething(taskNames[1], taskNames[1].Length)); // Shorter version, near-identical functionally.
// I think I can declare it also like this, but this will create tasks later
//IEnumerable<Task<Task<bool>>> myTasks = taskNames.Select(x => new Task<Task<bool>>(async () => await DoSomething(x, x.Length)));
taskNames[0] = "First";
taskNames[1] = "Second";
Debug.WriteLine($"Tasks created");
var results = await Task.WhenAll(myTasks.Select(x => x()));
Debug.WriteLine($"Finishing: {results.Select(x => x.ToString()).Aggregate((a, b) => a + "," + b) }");
警告:当您调用这些委托时,DoSomething
将同步执行到第一个 await
,因此行为相似,但 完全相同。
或者,您基于 IEnumerable
的解决方案也可以正常工作。只需在启动时编写迭代器方法和 yield return
任务。
就我个人而言,我会这样做:
string[] taskNames = new string[2];
taskNames[0] = "First";
taskNames[1] = "Second";
var results = await Task.WhenAll(taskNames.Select(n => DoSomething(n, n.Length)));
Debug.WriteLine($"Finishing: {results.Select(x => x.ToString()).Aggregate((a, b) => a + "," + b) }");
你的例子中不只是 "creating a Task
"。您正在调用一种方法 DoSomething
,即 returns 和 Task
。假设这些是 async
方法,Task
创建和启动发生在编译器生成代码的幕后。
此问题的解决方案很简单:在您准备好方法之前不要调用该方法 运行。想象一下您要求的行为在任何其他情况下会有多混乱。