【问题标题】:Task<t>.Wait never returnsTask<t>.Wait 永远不会返回
【发布时间】:2016-05-20 19:03:46
【问题描述】:

我有一个问题,我归结为这段代码 sn-p:

var task=new Task<int>(()=>5);

task.Wait();

问题是task.Wait() 永远不会返回。我过去编写的代码运行良好。

到目前为止我已经尝试过:

  • 将整个事情包装在一个异步函数中并在其上调用Wait(相同的行为)
  • 这最初是一个包含在 WaitAll 中的承诺列表,并在停止时调用 Wait
  • 尝试调用 Task.Start,但收到一个异常,指出 Task.Start 不适用于承诺风格的任务

那么,有什么想法吗?

编辑:

导致问题的完整代码 sn-p:

static void EfTest()
{
    _start = DateTime.Now;
    var task = CreateEfTask();

    var efTasks= Enumerable.Range(0, 1).Select(i => CreateEfTask()).ToList();

    var t= Task.WhenAll(efTasks);
    t.Wait();

    var results = t.Result;
}

private static Task<Result> CreateEfTask()
{
    return new Task<List<PricingRule>>(
        () => new global::Entities
            .Entities()
            .PricingRules
            .Where(pr => pr.IsEnabled).ToList())
            .ContinueWith(t => new Result 
            {
                PricingRules = t.Result,
                TimeSpan = DateTime.Now.Subtract(_start)
            });
}

Task.Start 放在t.Wait 之前会引发错误,指出您不能在promise stile Task 上使用start。

【问题讨论】:

  • 如果我执行 task.Start();它运行,但在我点击等待时它已经完成。所以,然后我的按预期运行 - 我没有收到错误
  • "尝试调用 Task.Start 但收到一个异常,指出 Task.Start 不适用于 promise 样式的任务" 我们可以查看具体的异常吗?

标签: c# task


【解决方案1】:

您的应用中的其他地方有问题

using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var task = new Task<int>(() => 5);
            task.Start();
            task.Wait();
        }
    }
}

每次都运行完成,没有错误。

【讨论】:

    【解决方案2】:

    来自Task.Wait 的任务永远不会结束,因为它正在等待的任务永远不会启动。您需要启动它们,例如

    var efTasks= Enumerable.Range(0, 1).Select(i => CreateEfTask()).ToList();
    
    foreach(var t in eTasks) {
        t.Start();
    }
    
    var t= Task.WhenAll(efTasks);
    t.Wait();
    

    虽然你可能想在CreateEfTask() 开始它:

    private static Task<List<PricingRule>> CreateEfTask()
    {
        var t = new Task<List<PricingRule>>(
            () => new global::Entities.Entities().PricingRules.Where(pr => pr.IsEnabled).ToList()).ContinueWith(t=>new Result {PricingRules = t.Result,TimeSpan = DateTime.Now.Subtract(_start)});
        t.Start();
        return t;
    }
    

    如果这是实体框架,您应该能够异步执行查询,而无需构建自己的任务并启动它们,例如

    private static Task<List<PricingRule>> CreateEfTask() {
        return new global::Entities.Entities().PricingRules.Where(pr => pr.IsEnabled).ToListAsync();
    }
    

    【讨论】:

    • 在重读 MSDN 示例时自己想通了这一点。谢谢:)
    【解决方案3】:

    您的代码没有启动任务。您需要在等待之前调用Start() 处理任务。

    你也可以使用Task.Factory.StartNew方法,功能上相当于用构造函数创建一个Task然后启动它,例如:

    var task = Task.Factory.StartNew(() => 5);
    
    task.Wait()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-22
      • 1970-01-01
      • 2019-11-15
      • 2011-07-25
      • 1970-01-01
      • 2012-10-02
      • 2013-02-18
      • 1970-01-01
      相关资源
      最近更新 更多