通过同步执行获取任务结果

时间:2014-05-12 01:49:27

标签: c# async-await

我很难理解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>对象。这就是我不知道如何“开始”的任务。还有其他想法吗?谢谢!

2 个答案:

答案 0 :(得分:4)

您可能正在寻找:

Task<bool> GetTrue()
{
    return Task.FromResult(true);
}

而不是:

Task<bool> GetTrue()
{
    return new Task<bool>(() => true);
}

在后一种情况下,您甚至无法启动您创建的任务。您需要使用Task.RunTask.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永远不会返回。