4

我有一个函数,我想在一个单独的线程中执行,避免两个线程访问相同的资源。另外我想确保如果线程当前正在执行,则停止该线程并开始执行新线程。这就是我所拥有的:

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 创建这个应用程序。很抱歉没有提到我想要完成的事情。我正在创建一个自动完成控件,在其中过滤大量数据。我不希望主窗口在我想过滤结果时冻结。我还想根据用户类型过滤结果。如果用户一次输入 5 个字母,我想停止所有线程,我只会对最后一个感兴趣。因为锁会阻塞所有线程,有时我创建的最后一个线程可能首先拥有锁。

4

3 回答 3

4

我认为你过于复杂了。如果您能够使用 4.0,则只需使用Task Parallel Library。有了它,您只需设置一个ContinueWith函数,以便必须以特定顺序发生的线程按照您指定的顺序完成。如果这不是您想要的,那么我实际上建议您不要使用线程,因为这听起来像是您试图强制进入并行的同步操作。

如果您只是想取消任务:那么这里有一个关于如何取消 TPL 任务的 SO 问题。如果您只想倾倒所有资源,除了最后一个,为什么还要浪费资源。

如果您不使用 4.0,那么您可以使用Background Worker完成同样的事情。只需要更多样板代码来完成同样的事情:)

于 2012-04-15T03:15:05.900 回答
0

我同意 Justin 的观点,即您应该使用 .NET 4 Task Parallel Library。但是,如果您想要完全控制,您不应该使用支持 LIFO 的默认任务计划程序,而是创建您自己的任务计划程序 ( http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler。 aspx ) 并实现您想要确定哪个任务获得偏好的逻辑。

除非您对 .NET 线程有深入的了解,否则不建议直接使用线程。如果您使用的是 .NET 4.0;任务和 TPL 是首选。

于 2012-04-15T04:37:31.313 回答
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);
}
于 2012-04-15T14:54:15.323 回答