C# 等待新任务<;T>;(…):任务未运行?
继续提问: 在前面提到的问题中,我有以下函数返回Task类型的对象(用于增量测试):C# 等待新任务<;T>;(…):任务未运行?,c#,asynchronous,async-await,task,C#,Asynchronous,Async Await,Task,继续提问: 在前面提到的问题中,我有以下函数返回Task类型的对象(用于增量测试): private静态任务GetInstance(){ 返回新任务((Func)(异步()=>{ 等待SimpleMessage.ShowAsync(“测试”); 返回新对象(); } ) ); } 当我调用等待GetInstance()时,函数被调用(我假设任务被返回,因为没有抛出异常),但任务就在那里 我只能猜测我做错了 我不希望此函数返回已在运行的任务(即命令式任务) 如何异步运行此函数返回的任务?创建已启
private静态任务GetInstance(){
返回新任务((Func)(异步()=>{
等待SimpleMessage.ShowAsync(“测试”);
返回新对象();
} ) );
}
当我调用等待GetInstance()时代码>,函数被调用(我假设任务被返回,因为没有抛出异常),但任务就在那里
我只能猜测我做错了
我不希望此函数返回已在运行的任务(即命令式任务)
如何异步运行此函数返回的任务?创建已启动的任务
尝试按如下方式创建任务:
Task.Factory.StartNew<object>((Func<Task<object>>) ...);
private static Func<object> GetFunction( ) {
return (Func<object>)(( ) => {
SimpleMessage.Show( "TEST" );
return new object( );
} );
}
然后获取它,并在需要时在新的任务中运行它(还要注意,我从lambda表达式中删除了async/await
,因为您已经将其放入任务中了):
好的,我想我已经弄明白了。请检查此代码:
class Program
{
public static void Main(string[] args)
{
// Only RUN the task as needed. FooGet
// still allows you to generalize your task.
Task.Run(() =>
{
dynamic value = FooGet();
value.RunSynchronously();
Console.WriteLine(value.Result.Result.ToString());
});
while (true) Thread.Sleep(100);
}
private static Task<object> FooGet()
{
var task = new Task<object>(() => {
return asyncBar();
});
return task;
}
private async static Task<object> asyncBar()
{
// do work!
return "Hello, world!";
}
}
类程序
{
公共静态void Main(字符串[]args)
{
//仅根据需要运行任务。FooGet
//仍然允许您概括您的任务。
Task.Run(()=>
{
动态值=FooGet();
value.RunSynchronously();
WriteLine(value.Result.Result.ToString());
});
while(真)线程。Sleep(100);
}
私有静态任务FooGet()
{
变量任务=新任务(()=>{
返回asyncBar();
});
返回任务;
}
专用异步静态任务asyncBar()
{
//干活儿!
返回“你好,世界!”;
}
}
您在那里遇到了一个糟糕的设计。在这些限制条件下,我会尽力为你做点事情
延迟启动任务的唯一方法是使用Task.start
方法。(您也可以使用同步运行
,但这并没有真正利用任何tasks功能。此时,task将成为一个无线程的惰性对象
因此,请使用Task.Start
方法
wait
不会启动任务。它会等待已经运行的任务。因此wait new Task(()=>{})
总是永久冻结
这里还有一个问题:
return new Task<object>( (Func<Task<object>>)(async ( ) => {
await SimpleMessage.ShowAsync( "TEST" );
return new object( );
} ) );
返回新任务((Func)(async()=>{
等待SimpleMessage.ShowAsync(“测试”);
返回新对象();
} ) );
当您启动该任务时,它将几乎立即完成,任务。Result
将保留另一个任务-异步lambda返回的任务。我怀疑这是您想要的。很难做到这一点,我不知道您需要什么
这闻起来像是XY问题。你能详细说明你想要完成什么吗?感觉你给了自己不必要的限制。你永远不应该使用任务构造函数(或任务.启动)
我不希望此函数返回已在运行的任务(这是必需的)
那么,您想返回一些在调用之前不会执行的代码吗?这是一个委托,而不是任务
private static Func<Task<object>> GetInstance()
{
return async () =>
{
await SimpleMessage.ShowAsync("TEST");
return new object();
};
}
您正在等待GetInstance
,这就是您的方法在那里等待的原因。它仍然是一个异步调用,因为线程可以被释放等待。我认为您将异步执行与多任务混合在一起。不清楚您在寻找什么,但也许?如果您实际上不知道,我不太理解为什么有必要这样做要开始获取实例,为什么要在该时间点调用GetInstance()
?可能需要类似Func
或Lazy
的内容,因此可以推迟对GetInstance()的调用
。我需要挂起对象而不运行它,因为该任务需要是一个可以取消的任务。我需要监视运行状态,以确定是否应该启动、取消、重新启动该对象,或者是否需要对用户的愚蠢行为大喊大叫……异步方法应该返回一个任务
,该任务将完成ete在某个时间点没有被显式启动。我会维护Func
实例,以便在需要时创建任务。等等-这不会启动任务吗?我需要返回任务而不启动它,然后再次启动它。我认为我对此非常明确(如果它没有启动任务,那么也可以,但这看起来像是它返回了一个已经在运行的任务…)当然,我假设这是您想要的,因为您正在等待它。否则,您应该调用task.start()?我修改了我的答案,希望它有助于解决我正在处理的情况的复杂性。这个问题超出了考虑范围(TL;DR:我做错了).然而,你的答案是创建任务并在不启动的情况下返回任务的正确方法。我认为最好将其纳入聊天中-不需要在此处转录战争与和平…现在我只需要找出如何在没有提示的情况下启动聊天会话…丁有一个发展…请查看你为什么要使用dynamic
何时知道类型?出于某种原因,编译器无法识别嵌套任务。使用dynamic可以跳过编译器,并在运行时获取第二个任务结果。这是因为FooGet()
正在创建并返回任务,而不是任务
(实际上是这样的)。谢谢-但这比你想象的要多。我需要这个任务,因为我需要它来支持任务取消和重新启动。我不想用我认为与当前问题无关的细节来解决这个问题。@Will:取消可以很好地解决这个问题。你说的“重新启动”到底是什么意思
class Program
{
public static void Main(string[] args)
{
// Only RUN the task as needed. FooGet
// still allows you to generalize your task.
Task.Run(() =>
{
dynamic value = FooGet();
value.RunSynchronously();
Console.WriteLine(value.Result.Result.ToString());
});
while (true) Thread.Sleep(100);
}
private static Task<object> FooGet()
{
var task = new Task<object>(() => {
return asyncBar();
});
return task;
}
private async static Task<object> asyncBar()
{
// do work!
return "Hello, world!";
}
}
return new Task<object>( (Func<Task<object>>)(async ( ) => {
await SimpleMessage.ShowAsync( "TEST" );
return new object( );
} ) );
private static Func<Task<object>> GetInstance()
{
return async () =>
{
await SimpleMessage.ShowAsync("TEST");
return new object();
};
}
var func = GetInstance();
// Delegate has not started executing yet
var task = func();
// Delegate has started executing
var result = await task;
// Delegate is done