线程 - 保证获得最后一个结果



我有几个线程调用方法。它看起来像这样:

public void DoWork(params int[] initialConditions)
{
//Do a lot of work
}

但是,如果条件变化很快,我会得到很多陈旧的中间结果,因为我无法足够快地完成计算。我知道!我将修改代码,使其如下所示:

public void DoWork(params int[] initialConditions)
{
if(Monitor.TryEnter(syncLock)
{
//Do a lot of work
Monitor.Exit(syncLock);
}
}

现在我不会费心做计算,除非我之前的计算完成。在快速变化的情况下,我会有点落后,但不会比我本来会更多,我不会浪费时间做所有额外的工作来获得陈旧的结果。

然而

一旦情况停止变化,我仍然有点过时,想要调用DoWork的最后一个线程早已不复存在。有没有办法告诉线程:

if no one is doing work
do work
else
wait to do work until after the other thread finishes
but
if a new thread arrives before you start doing work, leave without doing work.

此代码应满足伪代码描述的要求:

class Program
{
static object _workLockObject = new object();
static volatile int _currentPriority = 0;
static void Main()
{
Task t1 = new Task(() => TryDoWork(1));
Task t2 = new Task(() => TryDoWork(2));
Task t3 = new Task(() => TryDoWork(3));
t1.Start();
Thread.Sleep(100);
t2.Start();
Thread.Sleep(100);
t3.Start();
Console.ReadKey();
}
public static void TryDoWork(params int[] initialConditions)
{
var priotity = Interlocked.Increment(ref _currentPriority);
while (!Monitor.TryEnter(_workLockObject))// starting to wait when DoWork is available
{
if (priotity != _currentPriority) // if the thread has stale parameters
{
Console.WriteLine("DoWork skipped " + initialConditions[0]);
return;// skipping Dowork
}
Thread.Sleep(300);// Change the interval according to your needs
}
try // beginning of critical section
{
if (priotity == _currentPriority) // if the thread has the newest parameters
DoWork(initialConditions);
}
finally
{
Monitor.Exit(_workLockObject); // end of critical section
}
}
public static void DoWork(params int[] initialConditions)
{
Console.WriteLine("DoWork started " + initialConditions[0]);
Thread.Sleep(5000);
Console.WriteLine("DoWork ended " + initialConditions[0]);
}
}

Interlocked.Increment保证每个线程都有自己的优先级,并且最新的线程具有允许在可用时执行DoWork的优先级。

最新更新