2011-06-02 68 views
1

我发现在C#中调用TaskEx.Delay与异步框架CTP当某种问题的异步框架TaskEx.Delay问题

public async Task<string> TestAsync() { 
    return await TaskEx.RunEx<string>(async() => { //in real app this is time consuming code so this line is so complex 
      await TaskEx.Delay(1000); 
      return "test; 
     }); 
} 

public async void Test { 
    var count = 0; 
    while(count < 100) { 
     var val = await TestAsync(); 
     Console.WriteLine(val); // in real app this line adds elements to observable collection binded to ListBox 
     count++; 
    } 
} 

在控制台上输出出现一次主要是(有时是两个三次)但不是我所期望的100倍。

编辑:

它不控制台应用程序(上面的代码被简化)它是WP7应用程序。没有使用延迟它工作正常。

+1

这不是您正在运行的实际代码 - 您已经在等待非异步方法。如果你能想出一个简短但完整的程序,那真的会有所帮助。目前我无法访问编译器,但通过一个完整的应用程序,我至少可以更多地诊断正在发生的事情。 – 2011-06-02 17:15:59

+0

如果您认为TaskEx.Delay有问题,请尝试在控制台应用程序中显示它。 – 2011-06-02 21:13:19

+0

我很确定 - 从Microsoft Visual Studio异步CTP包打开示例项目(C#Windows Phone)Netflix。在MainPage.xaml.cs中的LoadMoviesAsync中添加等待TaskEd.Delay(1000),在78行右下方的imageCount + = movies.Length;并将pageCount更改为2以更好地查看结果。启动应用程序,在年份框中输入2000,然后上下移动列表中的项目。经过一段时间后,物品将停止加载,但仍有数百个物品剩下。删除延迟,没有问题! – awattar 2011-06-02 22:10:57

回答

2

这可能是由于您正在控制台应用程序中运行,而不是Windows应用程序。

由于没有同步上下文,因此异步在控制台应用程序中的行为与在Windows窗体,WPF或WCF应用程序中的行为不同。因此,await会回到一个线程池线程,并且实际上不会“等待”执行。

如果您在WPF或Windows窗体应用程序中运行它,它将按预期运行。


在附注中,您的方法过于复杂。你可以这样做:

public async Task<string> TestAsync() { 
    await TaskEx.Delay(1000); 
    return "test"; 
} 

这将,有效,工作方式与以前的方法相同,但用少得多的开销(和简单得多)。

+0

我认为说“异步在控制台应用程序中无法按预期工作”是误导性的,因为这显然取决于您的期望。异步的工作原理与*我希望它在控制台应用程序中一样,这是我测试大部分内容的地方:)示例代码当前不完整,但可以在控制台应用程序中以合理方式轻松运行。 – 2011-06-02 17:22:17

+0

@Jon:控制台模式应用程序中的异步和等待行为与Windows窗体,WPF,WCF等应用程序(当然,除非安装自定义同步上下文)显着不同。由于线程同步和许多问题发挥作用,所发生的事情的正常指导会发生显着变化。是的,使用异步编写合理的控制台模式应用程序是完全可能的,但它需要您真正关注自己在做什么。 – 2011-06-02 17:26:44

+0

@Jon:更好的措辞? :) – 2011-06-02 17:30:49

2

这是因为方法Test确实是一个异步方法。 C#编译器只是让你通过void返回类型来隐藏它。所以,如果你的主要方法如下所示

public static void Main() { 
    Test(); 
} 

那就不是实际运行Test,并等待它完全完成。这实际上是安排Test运行,它的完成将在未来某个时刻发生。因此,您看到不同的输出是有道理的,因为它与时间有关。