2015-09-26 113 views
2

我有一個WPF窗口,需要對SizeChanged事件做出反應。但是,只有在500毫秒時間內沒有進一步的SizeChanged事件(類似於BindingBase.Delay提供的行爲)時,它才應執行處理。但是,我注意到,當在調試模式下編譯爲x64時,此代碼會導致UI在調整大小時啓動滯後;在重繪的窗口中有明顯的延遲。我認爲這是由於OperationCanceledException在UI線程上被序列化,拋出並被捕獲。下面的代碼消除了問題:等待太慢;異步方法可以忽略取消嗎?

Task.Delay(500, lastCts.Token).ContinueWith(
     _ => 
     { 
      myTextBox.Text = string.Format("({0},{1})", this.Width, this.Height); 
     }, 
     lastCts.Token, 
     TaskContinuationOptions.NotOnCanceled, 
     TaskScheduler.FromCurrentSynchronizationContext()); 

我的問題是:是否有配置異步方法在UI線程上,才恢復處理,如果等待任務未取消的一個乾淨的方式?或者是這種邊界情況之一,由於事件發生的頻率,我們不應該使用等待,而是恢復到可提供更多控制的舊ContinueWith模式(如TaskContinuationOptions.NotOnCanceled)?

+0

檢查[this](http://stackoverflow.com/q/21611292/1768303)。您可以以非常相似的方式使用'AsyncOp'。 – Noseratio

回答

4

當有一個500毫秒的時間段

只要你有一個「時間」的要求沒有進一步SizeChanged將事件只宜進行處理,這是你應該使用Rx一個很明顯的標誌。像這樣的東西應該工作:

Observable.FromEventPattern<SizeChangedEventHandler, SizeChangedEventArgs>(h => SizeChanged += h, h => SizeChanged -= h) 
    .Throttle(TimeSpan.FromMilliseconds(500)) 
    .ObserveOn(SynchronizationContext.Current) 
    .Subscribe(_ => 
    { 
     myTextBox.Text = string.Format("({0}, {1})", this.Width, this.Height); 
    }); 
+0

如果任何人需要從回調中執行異步可取消操作,請參閱[使用取消支持在TextChanged上限制搜索查詢](http://kasperholdum.dk/2013/04/throttling-search-queries-on-textchanged- with-cancellation-support /),這與上面大致相同,但使用'Scan'爲回調提供新的'CancellationTokenSource'。 – Douglas