2014-09-20 100 views
0

在我的wpf應用程序中,我知道我應該更新主線程上的UI元素。我所做的是使用主窗口調度程序來執行此操作。我只是好奇,看看爲什麼這個代碼不起作用:爲什麼內部任務不執行?

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.Loaded += MainWindow_Loaded;    
    } 

    void MainWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     Task.Factory.StartNew(() => 
     { 
      Console.Write("test"); 

      Task.Factory.StartNew(() => 
      { 
       // why does this code does not execute!! ??? 
       Thread.Sleep(1000); 
       txt.Text = "Testing"; 
      }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); 

     });      
    } 
} 

爲什麼內部任務不執行?換句話說,我的程序永遠不會到達Thread.Sleep(1000);這是爲什麼?

+0

你確定它沒有執行?問題可能在這裏'txt.Text =「測試」;'這不會工作,因爲你不在UI線程上。將其替換爲寫入或創建一箇中斷點以驗證 – thumbmunkeys 2014-09-20 16:28:19

+0

我從來沒有遇到過斷點是的,我確信它不會執行。我只是問這個問題了解更多有關任務... – 2014-09-20 16:44:47

+0

可能重複[使用TaskScheduler.FromCurrentSynchronizationContext更新任務中的UI](http://stackoverflow.com/questions/17418208/update-ui-in-task-using -taskscheduler-fromcurrentsynchronizationcontext) – thumbmunkeys 2014-09-20 17:15:56

回答

3

當調用線程沒有同步上下文時,TaskScheduler.FromCurrentSynchronizationContext()會引發InvalidOperationException異常,即SynchronizationContext.Current返回null。

所以,爲了趕UI的TaskScheduler,你應該早點得到它:

void MainWindow_Loaded(object sender, RoutedEventArgs e) 
{ 
    var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
    Task.Factory.StartNew(() => 
    { 
     Console.Write("test"); 

     Task.Factory.StartNew(() => 
     { 
      Thread.Sleep(1000); 
      txt.Text = "Testing"; 
     }, CancellationToken.None, TaskCreationOptions.None, uiScheduler); 

    });      
} 

您還可以使用延續任務,你需要的線程上運行它:

void MainWindow_Loaded(object sender, RoutedEventArgs e) 
{ 
    var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
    Task.Factory.StartNew(() => 
    { 
     Console.Write("test"); 
    }).ContinueWith(() => 
     { 
      Thread.Sleep(1000); 
      txt.Text = "Testing"; 
     }, CancellationToken.None, TaskCreationOptions.None, uiScheduler); 
} 
0

你可以直接使用調度員:

public partial class MainWindow : Window 
    { 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.Loaded += MainWindow_Loaded; 
    } 

    void MainWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     Task.Factory.StartNew(() => 
     { 
     Console.Write("test"); 
     Thread.Sleep(1000); 

     Application.Current.Dispatcher.BeginInvoke(
      DispatcherPriority.Normal, new Action(() => 
      { 
      txt.Text = "Testing"; 
      })); 
     }); 
    } 
    } 
相關問題