当前位置 : 主页 > 编程语言 > c语言 >

c# – .NET并发问题:我可以将信号量传递给另一个线程

来源:互联网 收集:自由互联 发布时间:2021-06-25
我有多个共享使用信号量的线程.线程A保存信号量(使用锁定),线程B和C正在等待同一个信号量(也使用锁定).线程共享全局变量等. C#中有一种技术可以用来关闭线程B吗?我可以在A中设置一
我有多个共享使用信号量的线程.线程A保存信号量(使用锁定),线程B和C正在等待同一个信号量(也使用锁定).线程共享全局变量等.

C#中有一种技术可以用来关闭线程B吗?我可以在A中设置一个标志,并让线程B检查该标志并在它控制信号量后立即退出,但我不知道任何允许线程A将信号量输出到线程B的技术(并得到它)当线程B退出时返回)没有线程C占用控制的风险.

有人有任何建议如何解决这个设计问题?如果我接近这个错误,我可以根据需要重写程序.

[编辑]
一位意见提供者指出我使用了错误的术语.评论者是正确的 – 我正在使用一个关键部分,但考虑到一切都在一个过程中运行,在这个例子中,关键部分在功能上等同于更通用的术语“信号量”.

[编辑]
有人要求提供更多细节,所以在这里.

可以有多个线程执行代码A.只有一个线程执行代码B.

代码A:

private static Thread workerThread = null;

lock (lockObject)
{
    ... do some work ...

    if (...condition...)
    {
        if (workerThread != null)
        {
            // Kill the worker thread and continue only after it is dead.
            quitWorkerThread = true;
            // Wait for the thread to die.
            while (workerThread.IsAlive)
            {
                Thread.Sleep(50);
            }
            workerThread = null;
            quitWorkerThread = false;
        } // if (workerThread != null)
    } // if (...condition...)

    ... do some more work ...

    if (...condition...)
    {
        if (workerThread == null)
        {
            // Start the worker thread.
            workerThread = new Thread(WorkerThread);
            workerThread.Start();
        } // if (workerThread == null)
    } // if (...condition...)

    ... do even more work ...

} // lock (lockObject)

代码B:

private void WorkerThread()
{
    while (true)
    {
        if (quitWorkerThread)
        {
            return;
        }

        Thread.Sleep (2000);

        if (quitWorkerThread)
        {
            return;
        }

        lock(lockObject)
        {
            if (quitWorkerThread)
            {
                return;
            }
            ... do some work ...
        } // lock(lockObject)
    } // while (true)
} // WorkerThread

我怀疑Aaron解决方案的变体将是我使用的.我大多希望有一些更优雅的解决方案可用,但我怀疑像这个项目的其他一切,它是所有蛮力和角落情况:-(.

我很确定没有办法控制特定的线程,这似乎是你想要做的.您只能屈服于期间 – 由Windows调度程序决定接下来要运行的线程.

情况是你有三个线程,A,B和C.A有锁,B和C正在等待它,你想要一种方法来保证B接下来执行.

显而易见的解决方案是使用多个锁和/或同步原语.您可以将lock的语义与ManualResetEvent结合使用.使线程C等待事件和临界区,但线程B只需要等待临界区.在正常情况下,您在释放锁之前发出事件信号,然后由操作系统决定执行哪个线程.在特殊情况下,您根本不发出事件信号,在C仍然被阻止时保留线程B执行.

一旦B完成,然后你发出事件信号让C完成.

(未经测试的)示例是:

// Main thread is Thread A
object myLock = new Object();
AutoResetEvent myEvent = new AutoResetEvent(false);
ManualResetEvent completedEvent = new ManualResetEvent(false);

ThreadPool.QueueUserWorkItem(s =>
{
    for (int i = 0; i < 10000; i++)
    {
        lock (myLock)
        {
            // Do some work
        }
    }
    completedEvent.Set();
});  // Thread B

ThreadPool.QueueUserWorkItem(s =>
{
    for (int i = 0; i < 10000; i++)
    {
        myEvent.WaitOne();
        lock (myLock)
        {
            // Do some work
        }
    }
});  // Thread C

// Main loop for thread A
while (true)
{
    lock (myLock)
    {
        // Do some work
        if (SomeSpecialCondition)
            break;
        else
            myEvent.Set();
    }
}

completedEvent.WaitOne(); // Wait for B to finish processing
if (SomeSpecialCondition) // If we terminated without signaling C...
    myEvent.Set();        // Now allow thread C to clean up

这基本上使线程A负责线程C何时执行.线程A和B将正常竞争,但由线程A决定线程C的事件.

网友评论