2013-03-29 30 views
2

我有定期更新UI長搜索操作(發現occurence - >更新UI)長後臺進程令人耳目一新的UI WPF

我試圖實現其許多方面:

  1. 異步/ AWAIT

    public void PushButton() 
    { 
        await AsyncSearchAll(); 
    } 
    
    public async Task AsyncSearchAll(SearchPanelViewModel searchPanelViewModel, SearchSettings searchSettings, CancellationToken cancellationToken) 
    { 
        await Task.Factory.StartNew(() => 
                 { 
                  //searching for occurence 
                  //write it into panel 
                 }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); 
    } 
    
  2. BackgroundWorker的

    我想使用它,但我不知道想只用.ReportProgress()

  3. 簡單的後臺線程訪問UI與調用Dispatcher.BeginInvoke(()=>{//updating UI})

    /// <summary> 
    ///  Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow 
    { 
        public MainWindow() 
        { 
         InitializeComponent(); 
        } 
    
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
        { 
         var backgroundThread = new Thread(CountToTen) 
          { 
           IsBackground = true 
          }; 
         backgroundThread.Start(); 
        } 
    
        private void CountToTen() 
        { 
         for (int i = 1; i <= 10000; i++) 
         { 
          var j = i; 
          Dispatcher.BeginInvoke(new Action(() => Seconds.Text = j.ToString(CultureInfo.InvariantCulture))); 
         } 
        } 
    

所有的方法來完成線程後寫的所有數據。 有沒有任何方法來運行後臺任務,定期更新用戶界面,而不會通過阻止用戶界面來減慢程序?

+0

哪種方法提供了期望的結果? – takayoshi

+0

2和3是。但是如果ReportProgress對您來說不夠用,那就使用Dispatcher。 –

+0

請向我們展示(3)的簡單代碼,但無法正常工作 –

回答

3

如果您可以將「工作人員」邏輯與「UI更新」邏輯分開,那麼最好。

事情是這樣的:

public async Task AsyncSearchAll(SearchPanelViewModel searchPanelViewModel, SearchSettings searchSettings, CancellationToken cancellationToken) 
{ 
    while (..) 
    { 
    var results = await Task.Run(() => /* search more */); 
    /* update panel with results */ 
    } 
} 

但是如果你想實際進度更新,有辦法做到這一點:

public async void PushButton() 
{ 
    Progress<MyUpdateType> progress = new Progress<MyUpdateType>(update => 
    { 
    /* update panel */ 
    }); 
    await Task.Run(() => SearchAll(..., progress)); 
} 

public void SearchAll(SearchPanelViewModel searchPanelViewModel, 
    SearchSettings searchSettings, CancellationToken cancellationToken, 
    IProgress<MyUpdateType> progress) 
{ 
    while (..) 
    { 
    /* search more */ 
    if (progress != null) 
     progress.Report(new MyUpdateType(...)); 
    } 
} 
0

我認爲,在這樣的情況下,這是最好的,如果你能使用綁定。通過new collection synchronization,您可以執行諸如從另一個線程添加到綁定ObservableCollection<T>的操作。

如果這還不夠,你的目的,你可以使用Progress<T>到UI線程上執行的動作,當你產生其他線程上的一些結果(雖然,正如它的名字所暗示的,Progress主要是指報告進度)。

如果這樣也不合適,可以使用TPL Dataflow。您將有一個ActionBlock<T>TaskScheduler設置爲UI調度程序。您的工作線程會將生成的項目發送到該塊,並且該塊將在UI線程上處理它們。

相關問題