【发布时间】:2017-03-08 23:48:22
【问题描述】:
我在Func<Task>types 中定义了可变数量的任务,因此我可以定义任务但不能让它们自动启动。比如说:
Func<Task> task1Func = () => DoTask1Async();
以这种方式定义的一些任务返回值。我需要一种方法将此类任务的结果“传递”给以相同方式定义的后续任务的参数。所以,我想写:
Func<Task> task2Func = () => DoTask2Async(task1Func.Invoke().Result));
这样做的问题是task1Func.Invoke() 部分再次启动task1 任务,这是不好的。
我无法将输入重新构建为链延续,例如:
Func<Task> funcTasks = () => DoTask1Async().ContinueWith(t => DoTask2Async(t.Result));
因为我需要在代码中知道链中每个任务(即 DoTask1Async / DoTask2Async)完成运行其他代码的点。另一个问题是我不知道如何计算“链”中涉及多少任务。
我无法在任务结果完成时存储它们,因为任务需要像 task1Func 和 task2Func 这样以声明方式定义。
任务按定义的顺序处理,每个任务在处理下一个任务之前完成。任务的结果仅用于后续任务。
编辑
响应使用task1Func.Invoke().Result 的可运行代码的请求。创建一个新的 WPF 项目并向默认 Grid 添加一个按钮。然后清除 MainWindow.xaml.cs 文件并粘贴以下内容。这是最接近我真实项目的代码,同时删除了所有与问题无关的内容。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
// Declare first task that returns a result
Func<Task<int>> deferredTask1 = () => DoTask1Async();
// Declare second task using result of first.
// BUT this isn't good as it calls deferredTask1 AGAIN, so need another approach.
Func<Task> deferredTask2 = () => DoTask2Async(deferredTask1.Invoke().Result);
var item1 = new MyItem() { MyDeferredTask = deferredTask1 };
var item2 = new MyItem() { MyDeferredTask = deferredTask2 };
List<MyItem> items = new List<MyItem>();
items.Add(item1);
items.Add(item2);
await DoTasksAsync(items);
}
public static async Task<int> DoTask1Async()
{
return await Task<int>.Run(() => { return 3000; });
}
public static async Task DoTask2Async(int delay)
{
await Task.Delay(delay);
}
private async Task DoTasksAsync(IEnumerable<MyItem> items)
{
foreach (var item in items)
{
await item.MyDeferredTask();
}
}
private class MyItem
{
public Func<Task> MyDeferredTask { get; set; }
}
}
}
【问题讨论】:
-
你能把签名从
Func<Task>改成Func<Task,Task>吗? -
@ScottChamberlain,是的,这是可能的。
-
我认为我们需要一个更完整的示例来说明如何设置多个任务并将它们链接起来。使用示例中的
task1Func.Invoke().Result版本为我们创建runnable example。它将极大地帮助我们向我们展示如何以更好的方式做到这一点。 -
@ScottChamberlain ,请参阅我上面的编辑以响应您的请求。希望这会有所帮助。
-
你确定你是从正确的方向来的吗?像Dataflow 这样的东西可能是一个更好的起点吗?
标签: c# asynchronous async-await task-parallel-library task