Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Control On Separate UI Thread?

I am making a media player, now.. I have added a realtime search function to search for songs etc. (Some thing like WMP realtime search) i.e while you enter the keywords the searching happens.

During the searching process, accessing the database and loading an IEnumerable is done on another thread via a BackGroundProcess. The UI is updated by invoking a dispatcher of a UIElement.

This process is rather fast, but however while you enter the search keywords in the textbox, there seems to be a small lag, this is beacause the Listbox.ItemSource updating takes some time. i.e say you want to search for "Adele", when you type in "a", the search function loads the results for "A", but as we are typing the whole word "Adele" , it some time to display the "d" "e" "l" "e" and there is a slight lag in between these letters.

During this search process, when I stop updating the UI the search process seems very smooth, this only means to me that the Listbox is locking up the thread, so the rest of the player's UI is stuck there while the Listbox is done with its processing.

So I believe if I can put the Listbox Control to another UI thread, I can maintain the smooth flow of the player irrespective of the time taken to load the Listbox. FYI: Data Virutualization is there & ListBox has UI Virtualization is working

How can i put the ListBox control onto another UI Thread? WPF, C#

Thanks in advance :)

like image 946
Sylens Avatar asked Nov 07 '12 15:11

Sylens


2 Answers

If you are querying the database on every keypress - this is going to cause you some lag when typing fast (or even normally)

You would be better off throttling the request, we use this to throttle on the dispatcher thread.

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);
    } 


} 

Assuming you are not using MVVM, you could easily use this like so in your button click

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

Also worth a note : f you are using 4.5 there is the Delay property on bindings you could look at.

like image 59
Richard Friend Avatar answered Nov 02 '22 13:11

Richard Friend


In ASP.NET, usualy we use two techiniques

  • Wait for at most 3 char to begin the search.
  • Waiting some milliseconds after de user stop typing and before start the search, as the user types fast than some miliseconds, your search term will contains more than one char. This second option consists in start a timer when the user start to type and set this timer to zero (without stop it) every key pressed. When the user stops to typing for 2000 milliseconds (by example) you perform the search

A perfect approach is to combine this two techiniques: Only search if you have 3 or more chars in the search criteria, and use the timer.

like image 43
Ewerton Avatar answered Nov 02 '22 11:11

Ewerton