我有一个函数,我想在一个单独的线程中执行,避免两个线程访问相同的资源。 另外我想确保如果线程当前正在执行,那么停止该线程并开始执行新线程。这就是我所拥有的:
volatile int threadCount = 0; // use it to know the number of threads being executed
private void DoWork(string text, Action OncallbackDone)
{
threadCount++;
var t = new Thread(new ThreadStart(() =>
{
lock (_lock) // make sure that this code is only accessed by one thread
{
if (threadCount > 1) // if a new thread got in here return and let the last one execute
{
threadCount--;
return;
}
// do some work in here
Thread.Sleep(1000);
OncallbackDone();
threadCount--;
}
}));
t.Start();
}
如果我触发该方法5次,则所有线程都将等待锁定,直到锁定被释放。我想确保我执行最后一个线程。当线程等待成为锁的所有者时,我如何确定哪个是拥有锁的下一个。我希望他们按照我创建线程的顺序拥有资源...
修改
我不是用.net 4.0创建这个应用程序。很抱歉没有提到我想要完成的任务。我正在创建一个自动完成控件,我正在过滤大量数据。我不希望主窗口冻结eveytime我想过滤结果。我也希望在用户输入时过滤结果。如果用户一次键入5个字母,我想停止所有线程,我只会对最后一个感兴趣。因为锁会阻塞所有线程,有时我创建的最后一个线程可能首先拥有锁。
答案 0 :(得分:4)
我认为你过于复杂了。如果您能够使用4.0,那么只需使用Task Parallel Library即可。有了它,您可以设置ContinueWith函数,以便必须按照您指定的顺序完成必须按特定顺序执行的线程。如果这不是你想要的,那么我实际上会建议你不要使用线程,因为这听起来像是你试图强制并行的同步动作。
如果您只是想要取消任务:那么here is a SO question on how to cancel TPL tasks.如果您要将所有资源全部转储,除了最后一个之外,为什么要浪费资源。
如果您没有使用4.0,那么您可以使用Background Worker完成相同的操作。只需要更多的样板代码来完成同样的事情:)
答案 1 :(得分:0)
我同意Justin的意见,你应该使用.NET 4任务并行库。但是,如果您想要完全控制,则不应使用支持LIFO的默认任务计划程序,而是创建自己的任务计划程序(http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.aspx)并实现您想要确定哪个任务获得首选项的逻辑。
除非您对.NET线程有深入的了解,否则不建议直接使用线程。如果您使用的是.NET 4.0;任务和TPL是首选。
答案 2 :(得分:0)
这是我在阅读你们发布的链接后想出来的。我想我需要一个队列因此我实施了:
volatile int threadCount = 0;
private void GetPredicateAsync(string text, Action<object> DoneCallback)
{
threadCount++;
ThreadPool.QueueUserWorkItem((x) =>
{
lock (_lock)
{
if (threadCount > 1) // disable executing threads at same time
{
threadCount--;
return; // if a new thread is created exit.
// let the newer task do work!
}
// do work in here
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
threadCount--;
DoneCallback(Foo);
}));
}
},text);
}