C# Can';在使用任务构造函数时,不要使用结果启动任务

C# Can';在使用任务构造函数时,不要使用结果启动任务,c#,windows-runtime,windows-phone,windows-store-apps,async-await,C#,Windows Runtime,Windows Phone,Windows Store Apps,Async Await,我有一大堆任务,我希望能够按顺序运行。问题是,它们涉及大量的磁盘读取,我需要在使用每一个磁盘之间进行一些磁盘读取/写入,因此我希望能够创建一系列任务来从磁盘读取(并返回结果),但在准备好之前不启动它们 因此,我无法使用Task.Run或Task.Factory.StartNew。据我所知,这就是任务构造函数的用途 例: 有没有办法做到这一点?当前task.Start()引发异常:System.InvalidOperationException:其他信息:不能对承诺式任务调用Start。 编辑:应

我有一大堆任务,我希望能够按顺序运行。问题是,它们涉及大量的磁盘读取,我需要在使用每一个磁盘之间进行一些磁盘读取/写入,因此我希望能够创建一系列任务来从磁盘读取(并返回结果),但在准备好之前不启动它们

因此,我无法使用
Task.Run
Task.Factory.StartNew
。据我所知,这就是
任务
构造函数的用途

例:

有没有办法做到这一点?当前task.Start()引发异常:
System.InvalidOperationException:其他信息:不能对承诺式任务调用Start。

编辑:应该注意的是,它现在的样子有些奇怪。这是因为在每个步骤中,比如读取文件,我都会在返回数据之前对数据进行一些额外的逻辑处理。这应该不会影响代码,只要我可以在任务构造函数方法中进行异步调用

Edit2:似乎有人想让我更清楚地回答我的问题


有没有一种方法可以创建一个带有返回值的任务,但不启动它(可能使用
任务构造函数
),这样我就可以启动它并在其他时间等待该值。目前我收到了上面包含的异常。

我似乎已经解决了。基于

似乎我需要保留外部任务和调用任务的副本。单独开始,然后我可以按预期返回未包装的任务。例如:

public async Task<IEnumberable<Task<byte[]>>> ReadAllFiles()
{
    var folder = await ApplicationData.Current.LocalFolder;
    var files = await folder.GetFilesAsync();
    var fileTasks = files.Select(
        file => {
            var wrappedTask = new Task<Task<byte[]>>(
            async () => {
                return (await FileIO.ReadBufferAsync(file)).ToArray();
            });

            var unwrappedTask = wrappedTask.Unwrap();
            wrappedTask.Start();
            return unwrappedTask;
        });
    return fileTasks;
}
public异步任务ReadAllFiles()
{
var folder=wait ApplicationData.Current.LocalFolder;
var files=await folder.getfileasync();
var fileTasks=文件。选择(
文件=>{
var wrappedTask=新任务(
异步()=>{
return(wait FileIO.ReadBufferAsync(file)).ToArray();
});
var unwrappedTask=wrappedTask.Unwrap();
wrappedTask.Start();
返回未包装任务;
});
返回文件任务;
}

这将确保展开已完成,并计划内部任务(但不启动它)。

任务。运行
任务。工厂。开始新建
任务。任务
都适用于CPU限制的任务。您的任务是I/O绑定的

有没有一种方法,我可以创建一个返回值的任务,但不能启动它。。。以便我可以启动它,并在另一个时间等待值

当然;实际上,您需要的是一个具有
异步
兼容签名的委托。在本例中,a
Func
。我有更多与
异步
兼容的委托的示例

因此,您的示例可以是:

public async Task<IEnumberable<Task<byte[]>>> ReadAllFiles()
{
  var folder = await ApplicationData.Current.LocalFolder;
  var files = await folder.GetFilesAsync();
  var fileReaders = files.Select(file => new Func<Task<byte[]>>(
      async () => await FileIO.ReadBufferAsync(file)).ToArray()));
  return fileReaders;
}

var readers = await ReadAllFiles();
foreach(var func in readers)
{
  var bytes = await func();
  // Do other stuff
}
public异步任务ReadAllFiles()
{
var folder=wait ApplicationData.Current.LocalFolder;
var files=await folder.getfileasync();
var fileReaders=files.Select(file=>newfunc(
async()=>等待FileIO.ReadBufferAsync(file)).ToArray();
返回文件读取器;
}
var readers=wait ReadAllFiles();
foreach(读卡器中的var func)
{
var bytes=wait func();
//做其他事情
}

首先为什么要在此处使用
Start()
?因此,当您使用
Task.Run
Task.Factory.StartNew
时,它会自动启动它创建的任务。使用
task
构造函数创建任务时,它不会启动它。这意味着您必须调用
Task.Start()
来启动任务,否则如果您等待它,它将永远不会返回。是的,但是您的
ReadAllFiles()
返回一个延迟序列,因此即使您使用
Task.Run()
,只有在我没有考虑的
foreach
中迭代任务时,
任务才会启动。我试试看。因此,即使它通过Task.Run返回任务,在枚举之前它实际上不会调用Select lambda?确切地说,LINQ通常就是这样工作的。
public async Task<IEnumberable<Task<byte[]>>> ReadAllFiles()
{
    var folder = await ApplicationData.Current.LocalFolder;
    var files = await folder.GetFilesAsync();
    var fileTasks = files.Select(
        file => {
            var wrappedTask = new Task<Task<byte[]>>(
            async () => {
                return (await FileIO.ReadBufferAsync(file)).ToArray();
            });

            var unwrappedTask = wrappedTask.Unwrap();
            wrappedTask.Start();
            return unwrappedTask;
        });
    return fileTasks;
}
public async Task<IEnumberable<Task<byte[]>>> ReadAllFiles()
{
  var folder = await ApplicationData.Current.LocalFolder;
  var files = await folder.GetFilesAsync();
  var fileReaders = files.Select(file => new Func<Task<byte[]>>(
      async () => await FileIO.ReadBufferAsync(file)).ToArray()));
  return fileReaders;
}

var readers = await ReadAllFiles();
foreach(var func in readers)
{
  var bytes = await func();
  // Do other stuff
}