我很难理解async
和相应的行为。这是我正在尝试编写的程序的模型,以及我遇到的问题的重复:
namespace AsyncTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("starting....");
MyClass myClass = new MyClass();
myClass.DoSomeWork();
Console.WriteLine("ending....");
Console.ReadLine();
}
}
class MyClass
{
public bool DoSomeWork()
{
return GetTrue().Result;
}
Task<bool> GetTrue()
{
return new Task<bool>(() => true);
}
}
}
当我进行GetTrue().Result
调用时,它永远不会返回。我的Task<bool> GetTrue()
方法是一种用于repro目的的虚拟方法,但我不太确定为什么它永远不会回来。但如果我有这个,它就会回来:
namespace AsyncTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("starting....");
MyClass myClass = new MyClass();
myClass.DoSomeWork();
Console.WriteLine("ending....");
Console.ReadLine();
}
}
class MyClass
{
public async void DoSomeWork()
{
await GetTrue();
}
Task<bool> GetTrue()
{
return new Task<bool>(() => true);
}
}
}
问题是,我的repro我想要初始行为。我不希望async void
用于调用方法。我希望能够从我的“正常”方法中返回bool
。我怎样才能做到这一点?如何让第一个示例运行并实际从bool
返回DoSomeWork()
?
提前谢谢。
编辑:谢谢你的回答。我认为问题在于,我的GetTrue()
方法不是真正的复制品。在我的方法中,我没有生成实际的Task<bool>
对象。这实际上是对Task.Factory.FromAsync<bool>()
的调用,即创建Task<bool>
对象。这就是我不知道如何“开始”的任务。还有其他想法吗?谢谢!
答案 0 :(得分:4)
您可能正在寻找:
Task<bool> GetTrue()
{
return Task.FromResult(true);
}
而不是:
Task<bool> GetTrue()
{
return new Task<bool>(() => true);
}
在后一种情况下,您甚至无法启动您创建的任务。您需要使用Task.Run
或Task.RunSynchronously
启动它。通常,您不能通过new Task()
直接创建任务。查看Stephen Toub的"Task.Factory.StartNew" vs "new Task(...).Start"和"Task.Run vs Task.Factory.StartNew"。
根据您尝试实现的目标,您可能会想要这样做:
Task<bool> GetTrue()
{
return Task.Run(() => true);
}
然而,通常这会变成一种已知的反模式,请检查"Should I expose asynchronous wrappers for synchronous methods?&#34;。
更新了以解决评论:
...上下文是WCF服务。 Task.Factory.FromAsync() call是包装Begin ...()和End ...()函数的 服务已推向消费者。但我认为没办法真正开始 任务,它只是挂起。 ...是客户端进行WCF调用。客户端应用程序是一个 Windows Phone 8应用程序。
您在UI线程上遇到死锁,因为您正在阻止待处理任务的结果(使用task.Result
)。任务本身无法完成,因为await
延续是异步发布到WP8应用程序的UI线程的调度程序循环,现在已被阻止。 Stephen Cleary在his blog中详细解释了这一点。为避免这种情况,您应该使用"async all the way down"编程模型。它实际上意味着您应该创建UI事件和命令处理程序async
,并在那里var result = await task
而不是var result = task.Result
。
答案 1 :(得分:2)
你需要先做任务才能做任何事情。调用Run
会为你做这件事:
Task<bool> GetTrue()
{
return Task.Run(() => true);
}
这给出了您期望的输出。 Result
是阻止通话。如果您的Task
实例永远不会启动.. Result
永远不会返回。