5

私は今、メディア プレーヤーを作っています.. 曲などを検索するためのリアルタイム検索機能を追加しました (WMP リアルタイム検索のようなもの) つまり、キーワードを入力している間に検索が行われます。

検索プロセス中、データベースへのアクセスと IEnumerable の読み込みは、BackGroundProcess を介して別のスレッドで行われます。UI は、UIElement のディスパッチャを呼び出すことによって更新されます。

このプロセスはかなり高速ですが、テキスト ボックスに検索キーワードを入力している間は、Listbox.ItemSource の更新に時間がかかるため、少しラグがあるようです。たとえば、「Adele」を検索するとします。「a」と入力すると、検索機能は「A」の結果をロードしますが、「Adele」という単語全体を入力しているため、「d」を表示するのに時間がかかります。 " "e" "l" "e" で、これらの文字の間にはわずかなずれがあります。

この検索プロセス中に、UI の更新を停止すると、検索プロセスが非常にスムーズに見えます。これは、リストボックスがスレッドをロックしていることを意味するだけです。そのため、リストボックスの処理が完了している間、プレーヤーの UI の残りの部分はそこにとどまります。 .

したがって、Listbox コントロールを別の UI スレッドに配置できれば、Listbox の読み込みにかかる時間に関係なく、プレーヤーのスムーズなフローを維持できると思います。参考までに: データ仮想化があり、ListBox には UI 仮想化が機能しています

ListBox コントロールを別の UI スレッドに配置するにはどうすればよいですか? WPF、C#

前もって感謝します :)

4

2 に答える 2

5

キーを押すたびにデータベースにクエリを実行している場合-これにより、高速で(または通常でも)入力するときに遅延が発生します

リクエストを調整したほうがよいでしょう。これを使用して、ディスパッチャ スレッドを調整します。

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


} 

MVVMを使用していないと仮定すると、ボタンクリックで簡単に使用できます

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

また、注目に値する: 4.5 を使用している場合は、参照できるバインディングにDelayプロパティがあります。

于 2012-11-07T16:02:14.687 に答える
1

ASP.NET では、通常、2 つの手法を使用します。

  • 検索を開始するには、最大で 3 文字まで待ちます。
  • ユーザーが入力を停止してから検索を開始するまでに数ミリ秒待機すると、ユーザーは数ミリ秒より速く入力するため、検索語には複数の文字が含まれます。この 2 番目のオプションは、ユーザーが入力を開始したときにタイマーを開始し、キーを押すたびにこのタイマーを (停止せずに) ゼロに設定することで構成されます。ユーザーが 2000 ミリ秒の入力を停止すると (たとえば)、検索を実行します。

完璧なアプローチは、この 2 つの手法を組み合わせることです。検索基準に 3 文字以上ある場合にのみ検索し、タイマーを使用します。

于 2012-11-07T16:01:23.860 に答える