如何构建一个任务而不启动它?

G. *_*nev 42 c# task-parallel-library async-await

我想使用这个Task <>构造函数.我似乎无法得到正确的sntax可以有人纠正我的代码.

另外,我是否正确地认为,如果一个任务是以这种方式构建的,那么它是不是已经开始了?

我认为我需要的构造函数:

Task<TResult>(Func<Object, TResult>, Object)
Run Code Online (Sandbox Code Playgroud)

我的代码错误:

参数1:无法从'方法组'转换为' System.Func<object,int>'

static void Main(string[] args)
{
    var t = new Task<int>(GetIntAsync, "3"); //error is on this line
    ...
}

static async Task<int> GetIntAsync(string callerThreadId)
{
    ...
    return someInt;
}
Run Code Online (Sandbox Code Playgroud)

Vya*_*kov 30

var t = new Task<int>(() => GetIntAsync("3").Result);
Run Code Online (Sandbox Code Playgroud)

要么

var t = new Task<int>((ob) => GetIntAsync((string) ob).Result, "3");
Run Code Online (Sandbox Code Playgroud)

为了避免使用lambda,你需要编写一个这样的静态方法:

private static int GetInt(object state)
{
   return GetIntAsync(((string) state)).Result;
}
Run Code Online (Sandbox Code Playgroud)

然后:

var t = new Task<int>(GetInt, "3");
Run Code Online (Sandbox Code Playgroud)

  • 不确定这与 Q 有何对应,使用 Task.Result 会阻塞,这似乎不对,这与创建但不启动任务有何关系?您不能使用异步 lambda 然后等待结果吗? (4认同)
  • 这种方法使用异步到同步转换,这是危险的(死锁风险等)。因此,Theodor 的方法更好。 (4认同)
  • 在第二种情况下,您仍在关闭 `this`,因此您只使用 state 来传递两个变量之一。 (2认同)

The*_*ias 5

要使用Task接受object state参数的构造函数,您必须有一个也接受object参数的函数。一般这样是不方便的。此构造函数存在的原因是为了避免在热路径中分配对象(闭包)。对于正常使用,闭包的开销可以忽略不计,避免它们会无缘无故地使您的代码复杂化。所以是你应该使用的构造函数:

public Task (Func<TResult> function);
Run Code Online (Sandbox Code Playgroud)

...以这个 lambda 作为参数:

() => GetIntAsync("3")
Run Code Online (Sandbox Code Playgroud)

不过,您的情况有一个特点:您传递给构造函数的 lambda 返回一个Task<int>. 这意味着泛型类型TResult被解析为Task<int>,因此您最终会得到一个嵌套任务:

var t = new Task<Task<int>>(() => GetIntAsync("3"));
Run Code Online (Sandbox Code Playgroud)

启动外部任务将导致创建内部任务。要获得最终结果,您必须使用await运算符两次,一次用于完成外部任务,另一次用于完成内部任务:

static async Task Main(string[] args)
{
    var outerTask = new Task<Task<int>>(() => GetIntAsync("3"));
    //...
    outerTask.Start(); // or outerTask.RunSynchronously() to use the current thread
    //...
    Task<int> innerTask = await outerTask; // At this point the inner task has been created
    int result = await innerTask; // At this point the inner task has been completed
}
Run Code Online (Sandbox Code Playgroud)