2014-05-12 80 views
0

有人可以解释为什么SecondTask和加载事件不更新给定此代码的用户界面?Task.Run代码不执行

public Task First() 
{ 
    return Task.Run(
     () => 
     { 

      Task.Delay(4000); 
      Dispatcher.Invoke(() => 
      { 
       Title = "From First()"; 
      }); 
     }); 
} 
public Task Second() 
{ 
    return Task.Run(
     () => 
     { 
      Task.Delay(5000); 
      Dispatcher.Invoke(() => 
      { 
       Title = "From Second()"; 
      }); 
      Task.WaitAny(First()); 
     }); 

} 
    private void ParentWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     Second(); 
     Title = "From Event"; 
    } 

当我运行这段代码时,由于调用First(),只有窗体标题只改变一次。 没有别的东西被执行(至少从我所看到的,我可以看到达到的断点)。 我也尝试使用Task.WhenAny(First());而不是Task.WaitAny(First());

+0

那么,你是否设置了一些断点,然后通过调试器来查看发生了什么? – mason

+0

已达到断点,标题永不改变传递给First() – user3373870

+0

您在第二次完成后调用First,因此您会看到First –

回答

3

问题是Task.Delay没有被等待。 Task.Delay是一个异步睡眠,因此它会立即返回,如果您想在延迟之后实际继续执行,则需要await

那么在方法Second()中发生的是lambda表达式在后台线程上执行。当调用Task.Delay(5000)时,由于呼叫未被等待,呼叫立即返回,因此Title设置为From Second()。然后

public Task Second() 
{ 
    return Task.Run(
     () => 
     { 
      Task.Delay(5000); // need to await here 
      Dispatcher.Invoke(() => 
      { 
       Title = "From Second()"; 
      }); 
      Task.WaitAny(First()); 
     }); 

} 

First()被调用,因为Task.Delay(4000)也不会被期待已久的,它会立即将TitleFrom First()。所以最终的结果是,你只会看到From First()

public Task First() 
{ 
    return Task.Run(
     () => 
     { 

      Task.Delay(4000); // need to await here 
      Dispatcher.Invoke(() => 
      { 
       Title = "From First()"; 
      }); 
     }); 
} 

您也可能想除非你打算先设置你的标题From Eventawait调用的事件处理程序Second(),然后从Second()结果覆盖它。

private void ParentWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     Second(); // await this? 
     Title = "From Event"; 
    } 
+0

我认为你的意思是说Task.Delay(4000).Wait();而不是Task.Delay.Wait(4000); – user3373870

+0

ooops,谢谢 –

+0

感谢您的回答。 – user3373870

1

首先,您需要了解有关任务编程。请阅读有关my curation的文章。

任务被执行,你只是不要等他们完成。

async-await可以轻松完成异步工作,因此您不应该将UI与非UI代码混合使用。试试这个方法:

public async Task FirstAsync() 
{ 
    await Task.Delay(4000); 
    Title = "From First()"; 
} 

public async Task SecondAsync() 
{ 
    await Task.Delay(5000); 
    Title = "From Second()"; 
    await FirstAsync(); 
} 

private async void ParentWindow_Loaded(object sender, RoutedEventArgs e) 
{ 
    await SecondAsync(); 
    Title = "From Event"; 
} 

这会做你想要什么,这是更清洁的代码。