2012-11-07 42 views
5

我正在製作一個媒體播放器,現在..我添加了一個實時搜索功能來搜索歌曲等(有些東西像WMP實時搜索),即當您輸入關鍵字搜索發生時。獨立的UI線程上的WPF控件?

在搜索過程中,訪問數據庫並加載IEnumerable是通過BackGroundProcess在另一個線程上完成的。通過調用UIElement的調度器來更新UI。

此過程相當快,但是當您在文本框中輸入搜索關鍵字時,似乎有一個小滯後,這是因爲Listbox.ItemSource更新需要一些時間。 即你想搜索「阿黛爾」,當你輸入「a」時,搜索功能會加載「A」的結果,但是當我們輸入整個單詞「阿黛爾」時,有一段時間顯示「 d「」e「」l「」e「,這些字母之間有一點點滯後。

在此搜索過程中,當我停止更新UI時,搜索過程看起來非常流暢,這隻對我意味着Listbox鎖定了線程,所以當Listbox是完成其處理。

所以我相信如果我可以將Listbox控件放到另一個UI線程中,我可以保持播放器的平穩流動,而不管加載列表框的時間如何。 供參考:數據Virutualization有&列表框有UI虛擬化正在工作

我怎樣才能把ListBox控件到另一個UI線程? WPF,C#

感謝提前:)

+0

有效地,你不能...至少不能以我見過的任何可行的方式。 – Servy

+0

使用.net 4.5?現在有一個很好的綁定延遲屬性,這可能是一個簡單的勝利在這裏,基本上設置爲100毫秒,它只會更新綁定,如果用戶停止輸入的時間長度(或按下輸入或文本框失去焦點) – Andy

+1

只有一個UI線程。 –

回答

5

如果你在每一個按鍵查詢數據庫 - 這是怎麼回事打字快(甚至常)

你會過得更好節流的請求時,給你造成一定的滯後性,我們用這個油門調度程序線程。不使用MVVM

public static class DispatcherExtensions 
{ 
    private static Dictionary<string, DispatcherTimer> timers = 
     new Dictionary<string, DispatcherTimer>(); 
    private static readonly object syncRoot = new object(); 

    public static string DelayInvoke(this Dispatcher dispatcher, string namedInvocation, 
     Action action, TimeSpan delay, 
     DispatcherPriority priority = DispatcherPriority.Normal) 
    { 
     lock (syncRoot) 
     { 
      if (String.IsNullOrEmpty(namedInvocation)) 
      { 
       namedInvocation = Guid.NewGuid().ToString(); 
      } 
      else 
      { 
       RemoveTimer(namedInvocation); 
      } 
      var timer = new DispatcherTimer(delay, priority, (s, e) => 
       { 
        RemoveTimer(namedInvocation); 
        action(); 
       }, dispatcher); 
      timer.Start(); 
      timers.Add(namedInvocation, timer); 
      return namedInvocation; 
     } 
    } 


    public static void CancelNamedInvocation(this Dispatcher dispatcher, string namedInvocation) 
    { 
     lock (syncRoot) 
     { 
      RemoveTimer(namedInvocation); 
     } 
    } 

    private static void RemoveTimer(string namedInvocation) 
    { 
     if (!timers.ContainsKey(namedInvocation)) return; 
     timers[namedInvocation].Stop(); 
     timers.Remove(namedInvocation); 
    } 


} 

假設,你可以很容易地使用像這樣在你點擊鏈接

Dispatcher.CurrentDispatcher.DelayInvoke("UpdateSearch", 
     YourMethodThatStartsBackgroundThread,Timespan.FromSeconds(1)); 

也值得一記:F使用的是4.5存在Delay屬性上綁定你可以看看。

+0

謝謝你,我現在檢查一下! – Xero

+0

Yessss !!奇蹟般有效! 非常有用的一段代碼! – Xero

+0

@Xero你可能會從微軟的ReactiveExtensions中獲益。 (Rx)的。我看到的很多教程都向你展示瞭如何非常輕鬆地抑制查詢。 – Thelonias

1

在ASP.NET中,usualy我們使用了兩個techiniques

  • 等待最多3字符開始搜索。
  • 在用戶停止鍵入之後和開始搜索之前等待幾毫秒,因爲用戶鍵入的內容快於某些毫秒,那麼您的搜索詞將包含多個字符。 第二個選項包括啓動一個計時器,當用戶開始輸入時,按下每個按鍵將該計時器設置爲零(不停止)。當用戶停止鍵入2000毫秒(例如)時,您執行搜索

一個完美的方法是結合這兩種技術:只搜索如果您有3個或更多的字符在搜索條件,並使用計時器。