我正在创建一个自动完成控件,可在用户键入文本时进行更新。每次用户键入一个键时,都会触发一个新线程以过滤结果。结果来自网络,因此过滤需要大约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);
}
因此,您可以看到我在哪里快速键入“Hello”,然后将创建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.
答案 0 :(得分:2)
除了mellamokb的评论之外,听起来你根本不想要一个线程 pool - 你想要一个单个线程, single < / em>“下一个要执行的任务” - 如果已经有一个任务要执行,那么它将被新的任务覆盖。基本上类似于生产者/消费者队列,但只有一个“槽”被覆盖。
答案 1 :(得分:0)
在TPL数据流中,这正是BroadcastBlock
所做的:它将始终只记住发布给它的最后一项。如果您将其与容量限制为1的ActionBlock
相关联,则ActionBlock
的操作将按您希望的方式执行。
虽然仅仅为此使用TPL Dataflow可能没什么意义。