多等待句柄

3

我有如下代码:

public void MethodA()
{
    MyManualResetEvent.Reset();
}

public void MethodB()
{
    MyManualResetEvent.Set();
}

如果另一个线程调用了MethodA但未调用MethodB,则使用MyManualResetEvent.WaitOne()停止线程是可行的。

现在我想做的是能够调用MethodA两次,只有在调用MethodB两次而不是一次时,另一个线程才会继续执行。

我希望在System.Threading命名空间中有一些我不知道的东西。


使用两个事件和WaitMultiple可能吗? - Karel Petranek
2只是一个例子,我希望它适用于一般情况。即任意数量的调用对。这可能是一个想法,我可以使用重置事件列表或类似的东西吗?不确定这是否会引起问题或难以维护。 - George Duckett
一个关于.Net线程资源的良好概述 http://www.albahari.com/threading/threading.pdf - hatchet - done with SOverflow
3个回答

4

我已查看此内容,并阅读了 http://social.msdn.microsoft.com/Forums/en/parallelextensions/thread/aa49f92c-01a8-4901-9846-91bc1587f3ae 但似乎无法在我的情况下使其正常工作,因为我不确定如何使等待线程在当前计数为1而不为零的情况下继续执行。 - George Duckett

3
假设您不需要在调用MethodA时停止并发执行的BlockedMethod,那么最简单的解决方法可能是使用标准的Monitor类。 MethodAMethodB共享一个计数器,记录了没有相应调用MethodB的情况下调用MethodA的次数。只有当该计数为0时,BlockedMethod方法才会继续执行;否则,它将等待MethodB发出信号,表明现在可以继续执行。
object mylock = new object();
int count = 0;

public void MethodA()
{
    // record that MethodA is executing
    lock (mylock)
        count++;

    // other code...
}

public void MethodB()
{
    // other code...

    lock (mylock)
    {
        // MethodB has now finished running
        count--;

        // wake up other thread because it may now be allowed to run
        Monitor.Pulse(mylock);
    }
}

public void BlockedMethod()
{
    // wait until the number of calls to A and B is equal (i.e., count is 0)
    lock (mylock)
    {
        while (count != 0)
             Monitor.Wait(mylock);
    }

    // calls to A and B are balanced, proceed...
}

我认为这不会起作用,因为BlockedMethod线程可能正在等待并持有MyLock,这会阻止MethodB线程对计数进行递减,或者我误解了吗? - George Duckett
@George,“Monitor.Wait”将释放对“mylock”的锁定,然后阻塞直到被“MethodB”调用“Pulse”唤醒。或者,如果count==0,则会立即退出while循环,释放锁并继续执行其工作。请参阅关于Monitor.Wait的文档:http://msdn.microsoft.com/en-us/library/ateab679.aspx - Bradley Grainger
啊,好的,我没意识到Monitor.Wait也会释放它。我想我需要加强我的线程概念! - George Duckett
接受了这个答案,因为在我看来它是最简单的一个(甚至我也能理解!)。 - George Duckett

0

你可以使用 System.Threading.Semaphore 来完成这样的事情。

一个简单版本可能如下所示:

    System.Threading.Semaphore s1 = new System.Threading.Semaphore(2, 2);

    public void BeginSomething()
    {
        // This decrements the value of s1.
        s1.WaitOne();
    }

    public void EndSomething()
    {
        // This increments the value of s1.
        s1.Release();
    }

    public void BlockedMethod()
    {
        bool execute = true;
        // Try to get access.
        for (int i = 0; i < 2; i++)
        {
            if (!s1.WaitOne(0))
            {
                for (; i >= 0; i--)
                {
                    s1.Release();
                }
                execute = false;
                break;
            }
        }

        if (execute)
        {
            // This code is only executed if s1 has its starting value 2.

            for (int i = 0; i < 2; i++)
            {
                s1.Release();
            }
        }
    }

但我认为使用这种方法仍然需要一个信号量来控制函数对的平衡。


我已经看过信号量了,但它似乎允许多个(可配置数量的)线程访问某些东西(例如资源或代码块),导致更多线程需要等待。我不确定在我的情况下是否可以使用它。如果可以的话,一个例子就太好了。 - George Duckett
抱歉,我仍然不明白如何在调用对数不同的情况下使用它。 - George Duckett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接