C# 如何在不启动的情况下构建任务?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16066349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to construct a Task without starting it?
提问by G. Stoynev
I want to use thisTask<TResult>constructor. I can't seem to get the syntax right. Could someone correct my code?
我想使用这个Task<TResult>构造函数。我似乎无法正确使用语法。有人可以更正我的代码吗?
Also, am I right thinking that if a Taskis constructed that way, it's not started?
另外,我认为如果 aTask是这样构造的,它就没有开始吗?
The constructor I think I need is:
我认为我需要的构造函数是:
Task<TResult>(Func<Object, TResult>, Object)
The error I get is:
我得到的错误是:
Argument 1: cannot convert from 'method group' to '
System.Func<object,int>'
参数 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;
}
采纳答案by Vyacheslav Volkov
var t = new Task<int>(() => GetIntAsync("3").Result);
Or
或者
var t = new Task<int>((ob) => GetIntAsync((string) ob).Result, "3");
To avoid using lambda, you need to write a static method like this:
为避免使用 lambda,您需要编写这样的静态方法:
private static int GetInt(object state)
{
return GetIntAsync(((string) state)).Result;
}
And then:
进而:
var t = new Task<int>(GetInt, "3");
回答by Greg
//creating task
var yourTask = Task<int>.Factory.StartNew(() => GetIntAsync("3").Result);
//...
int result = yourTask.Result;
UPDATE:
更新:
Yes, unfortunately it does start the task. Use code as mentioned above instead:
是的,不幸的是它确实启动了任务。改用上面提到的代码:
//creating task
var yourTask = new Task<int>(() => GetIntAsync("3").Result);
//...
// call task when you want
int result = yourTask.Start();
回答by Theodor Zoulias
To use the Taskconstructor that accepts an object stateargument you must have a function that accepts an objectargument too. Generally this is not convenient. The reason that this constructor exists is for avoiding the allocation of an object (a closure) in hot paths. For normal usage the overhead of closures is negligible, and avoiding them will complicate your code for no reason. So thisis the constructor you should use instead:
要使用Task接受object state参数的构造函数,您必须有一个也接受object参数的函数。一般这样是不方便的。此构造函数存在的原因是为了避免在热路径中分配对象(闭包)。对于正常使用,闭包的开销可以忽略不计,避免它们会无缘无故地使您的代码复杂化。所以这是你应该使用的构造函数:
public Task (Func<TResult> function);
...with this lambda as argument:
...以这个 lambda 作为参数:
() => GetIntAsync("3")
There is one peculiarity in your case though: the lambda you pass to the constructor returns a Task<int>. This means that the generic type TResultis resolved to Task<int>, and so you end up with a nested task:
不过,您的情况有一个特点:您传递给构造函数的 lambda 返回一个Task<int>. 这意味着泛型类型TResult被解析为Task<int>,因此您最终会得到一个嵌套任务:
var t = new Task<Task<int>>(() => GetIntAsync("3"));
Starting the outer task will result to the creation of the inner task. To get the final result you'll have to use the awaitoperator twice, one for the completion of the outer task, and one for the completion of the inner task:
启动外部任务将导致创建内部任务。要获得最终结果,您必须使用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
}

