2013-03-29 27 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线程上处理它们。

相关问题