Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 线程-保证得到最后的结果_C#_Multithreading_Locking_Staleobjectstate - Fatal编程技术网

C# 线程-保证得到最后的结果

C# 线程-保证得到最后的结果,c#,multithreading,locking,staleobjectstate,C#,Multithreading,Locking,Staleobjectstate,我有几个线程调用一个方法。它看起来像这样: 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

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

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);
    }
}
然而,如果条件变化很快,我会得到很多陈旧的中间结果,因为我不能足够快地完成计算。我知道!我将修改代码,使其如下所示:

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]);
    }
}

互锁。增量
保证每个线程都有自己的优先级,最新线程有一个优先级,允许在可用时执行
DoWork

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

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]);
    }
}

互锁。增量
保证每个线程都有自己的优先级,最新的线程有一个优先级,允许在可用时执行
DoWork

理想的情况应该与Monitor.TryEnter版本一样干净,但不知何故,其行为与代码的psuedo代码版本类似,因此您的操作相互依赖?Do work仅取决于传入的初始条件,但会根据计算结果设置一些全局变量,因此对DoWork的各个线程调用不会相互依赖,但是它们确实会影响整个程序的结果。这听起来像是
ConcurrentStack
的工作。你不能去掉全局变量吗?理想的情况应该和监视器一样干净。TryEnter版本,但不知何故,其行为与代码的psuedo代码版本类似,因此您的操作相互依赖?Do work仅取决于传入的初始条件,但会根据计算结果设置一些全局变量,因此对DoWork的各个线程调用不会相互依赖,但是它们确实会影响整个程序的结果。这听起来像是
ConcurrentStack
的工作。你不能去掉全局变量吗?