我想使用this Task<> constructor。我似乎无法让sntax正确,有人可以更正我的代码。
另外,我是否正确地认为如果以这种方式构建任务,它是不是已经开始了?
我认为我需要的构造函数:
Task<TResult>(Func<Object, TResult>, Object)
我的代码错误:
参数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;
}
答案 0 :(得分:26)
var t = new Task<int>(() => GetIntAsync("3").Result);
或者
var t = new Task<int>((ob) => GetIntAsync((string) ob).Result, "3");
为了避免使用lambda,你需要编写一个这样的静态方法:
private static int GetInt(object state)
{
return GetIntAsync(((string) state)).Result;
}
然后:
var t = new Task<int>(GetInt, "3");
答案 1 :(得分:3)
要使用接受Task
参数的object state
构造函数,您还必须具有一个接受object
参数的函数。通常这不方便。该构造函数存在的原因是为了避免在热路径中分配对象(closure)。对于正常使用,闭包的开销可以忽略不计,避免它们会毫无理由地使您的代码复杂化。因此this是您应改用的构造函数:
public Task (Func<TResult> function);
...以此lambda作为参数:
() => GetIntAsync("3")
不过,您的情况有一个特殊之处:传递给构造函数的lambda返回Task<int>
。这意味着通用类型TResult
被解析为Task<int>
,因此您最终得到了一个嵌套任务:
var t = new Task<Task<int>>(() => GetIntAsync("3"));
启动外部任务将导致内部任务的创建。要获得最终结果,您必须两次使用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
}
答案 2 :(得分:1)
我发现异步 lambda 效果最好,因为:
.Start
,因此不可能忘记这样做。Func<Task<int>> f = async () => await WorkAsync(2);
Console.WriteLine("Sleeping before start");
await Task.Delay(100);
Console.WriteLine("Waking up to start");
var result = await f();
Console.WriteLine($"The work is done and the answer is: {result}");
结果如下:
Sleeping before start
Waking up to start
Starting 2
Ending 2
The work is done and the answer is: 4
答案 3 :(得分:-1)
.net 5 中的一种新方法(实际上我不知道你什么时候可以开始这样做,我现在正在使用 .net 5)
Task<int> MyStartLaterTask = null;
//... Some Time Later
MyStartLaterTask ??= GetIntAsync(string callerThreadId);
await MyStartLaterTask;
我很欣赏这并不完全是“预先定义并稍后使用”,但据我所知,这做了同样的事情。我有一个循环,我想定义一个只在需要时运行并且只运行一次的任务。这就是这样做的,它创建了一个我可以在第一次需要时分配的任务,然后在需要输出时等待它。
答案 4 :(得分:-3)
//creating task
var yourTask = Task<int>.Factory.StartNew(() => GetIntAsync("3").Result);
//...
int result = yourTask.Result;
更新:
是的,不幸的是它确实开始了这项任务。请使用上面提到的代码:
//creating task
var yourTask = new Task<int>(() => GetIntAsync("3").Result);
//...
// call task when you want
int result = yourTask.Start();