0

ユーザーがテキストを入力すると更新されるオートコンプリートコントロールを作成しています。ユーザーがキーを入力するたびに、結果をフィルタリングするために新しいスレッドが起動します。結果はネットワーク経由で送信されるため、フィルタリングに約1分かかります。これは私が持っているものに似ています:

    object _lock = new object();
    volatile static bool isThreadRunning=false ;
    private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
    {

        var text = textBox1.Text.ToUpper();
        ThreadPool.QueueUserWorkItem((o) =>
        {

            lock (_lock) // avoid multiple threads to be running at the same time
            {
                isThreadRunning = true;

                // do work in here

                isThreadRunning=false;
            }

        },text);
    }

したがって、「こんにちは」とすばやく入力する場所があるかどうかを確認できるように、5つのスレッドが作成され、そのうちの4つは最初のスレッドが終了するのを待つ必要があります。そのスレッドが終了すると、次のスレッドは実行を継続します。

実行を待機しているスレッドが4つある場合は、最後のスレッドのみを実行したいと思います。また、スレッドはランダムな順序でロックに入ります。どれが最後のものかをどうやって判断できますか。新しいスレッドが起動し、スレッドが現在実行中の場合は、そのスレッドをなんらかの方法でキャンセルできます。そうすれば、順序は常に正しいものになります。そのアルゴリズムをどのように実装できますか?


編集

これは私が解決したことです:

    class DoWorkOnce
    {

        static object _lock = new object();
        static Stack<Action> Work = new Stack<Action>();

        public static void Add(Action task)
        {
            Work.Push(task);
            DoSomeWork();                
        }

        private static void DoSomeWork()
        {                
            Task.Factory.StartNew(() =>
            {
                lock (_lock) // ensure that the following block of code is only executed at once
                {
                    if (Work.Count == 0) // if there is no items in the stack return
                        return;

                    Work.Pop()(); // get the last item in the stack and execute it


                    // remove the bottom of the stack by poping everything exept the top item
                    Action temp=null;
                    if(Work.Count>0)
                        temp = Work.Pop();

                    while (Work.Count > 0)
                        Work.Pop();

                    if (temp != null)
                        Work.Push(temp);
                }
            });
        }
    }

そして私はそのクラスを次のように使うことができます:

        string[] simulationOfTyping = new string[] { "H", "He", "Hel", "Hell", "Hello", "Hello ", "Hello W", "Hello Wo", "Hello Wor", "Hello Worl", "Hello World" };

        // simulate user typing
        foreach(var text in simulationOfTyping)
        {
            Thread.Sleep(50);
            DoWorkOnce.Add(() =>
            {
                Console.WriteLine(text);
                Thread.Sleep(1000);
            });
        }

        // the last item should execute always.
4

2 に答える 2

2

mellamokbのコメントは別として、スレッドプールはまったく必要ないようです。つまり、単一の「次に実行するタスク」を持つ単一のスレッドが必要です。実行するタスクがすでにある場合は、新しいスレッドによって上書きされます。 1。本質的には生産者/消費者キューに似ていますが、上書きされる「スロット」は1つだけです。

于 2012-04-20T20:35:24.087 に答える
0

TPL Dataflowでは、これがまさにそのBroadcastBlock機能です。常に、最後に投稿されたアイテムのみを記憶します。ActionBlock容量が1に制限されているにリンクすると、そのActionBlockアクションは希望どおりに実行されます。

これだけにTPLデータフローを使用することはおそらくあまり意味がありませんが。

于 2012-04-20T20:47:04.110 に答える