【发布时间】:2014-10-19 09:39:38
【问题描述】:
我有一堆任务希望能够按顺序运行。问题是,它们涉及大量磁盘读取,我需要在使用每个磁盘之间进行一些磁盘读取/写入,所以我希望能够创建一堆用于从磁盘读取的任务(并返回结果),但在我准备好之前不要启动它们。
因此,我不能使用Task.Run 或Task.Factory.StartNew。据我了解,这就是 Task 构造函数的用途。
例如:
public async Task<IEnumberable<Task<byte[]>>> ReadAllFiles()
{
var folder = await ApplicationData.Current.LocalFolder;
var files = await folder.GetFilesAsync();
var fileTasks = files.Select(
file => new Task<Task<byte[]>>(
async () => {
return (await FileIO.ReadBufferAsync(file)).ToArray();
}).Unwrap());
return fileTasks;
}
然后,在我的调用方法中我可以去:
var readTasks = await ReadAllFiles();
foreach(var task in readTasks)
{
task.Start(); // Throws exception
var bytes = await task; // If the previous line is commented out, does not return
// Do other stuff
}
有没有办法做到这一点?现在 task.Start() 抛出异常:System.InvalidOperationException: Additional information: Start may not be called on a promise-style task.。
编辑:应该注意的是,它目前的外观有些奇怪。这是因为在读取文件等每个步骤中,我在返回数据之前都会对数据进行一些额外的逻辑处理。这应该不会影响代码,只要我可以在 Task 构造方法中进行异步调用即可。
Edit2:似乎有人希望我对我的要求更清楚。
有没有一种方法可以创建具有返回值的任务,但不启动它(可能使用Task<TResult> constructor),以便我可以启动它并在其他时间等待该值。目前我收到了上面包含的异常。
【问题讨论】:
-
你为什么要在这里使用
Start()? -
因此,当您使用
Task.Run或Task.Factory.StartNew时,它会自动启动它创建的任务。当您使用Task构造函数创建任务时,它不会启动它。这意味着您必须调用Task.Start()来启动任务,否则如果您等待它,它将永远不会返回。 -
是的,但是你的
ReadAllFiles()返回一个惰性序列,所以即使你使用了Task.Run(),Tasks 只有在你在foreach中迭代它们时才会启动。 -
我没有考虑过。我会试一试。所以即使它通过Task.Run返回一个Task,在枚举之前它不会真正调用Select lambda?
-
没错,一般 LINQ 就是这样工作的。
标签: c# windows-runtime windows-phone windows-store-apps async-await