向休眠线程发出信号

问题描述 投票:0回答:3

我是 C# 中多线程的新手,对所有线程的内容感到困惑。 这就是我想要的:

public class TheClass
{
    Thread _thread;
    bool _isQuitting;
    bool _isFinished;
    object jobData;
    public void Start()
    {
        jobData = new object();
        _thread = new Thread(new ThreadStart(Run));
        _thread.Start();
    }
    private void Run()
    {
        while (!_isQuitting)
        {
            lock (jobData) // or should i use mutex or monitor?
            {
                DoStuff();
            }
            // sleep till get triggered
        }
        DoCleanupStuff();
        _isFinished = true;
    }

    public void AddJob(object param)
    {
        jobData = param;
        //wake up the thread
    }
    public void Stop()
    {
        _isQuitting = true;
        //wake up & kill the thread
        //wait until _isFinished is true
        //dispose the _thread object
    }
}

在本课程中,实现注释掉的短语和整体性能的最有效方法是什么?

c# multithreading events triggers
3个回答
2
投票

考虑使用

Monitor.Wait()
Monitor.Pulse()

例如:

object locker = new object();

private void Run()
{
    while (!_isQuitting)
    {
        lock (locker)
        {
            Monitor.Wait(locker);
            DoStuff(jobData);
        }
    }
    DoCleanupStuff();
}

public void AddJob(object param)
{
    // Obtain the lock first so that you don’t
    // change jobData while the thread is processing it
    lock (locker)
    {
        jobData = param;
        Monitor.Pulse(locker);
    }
}

public void Stop()
{
    lock (locker)
    {
        _isQuitting = true;
        Monitor.Pulse(locker);
    }

    // Wait for the thread to finish — no need for _isFinished
    _thread.Join();
}

但是,请注意,在我的代码中,您仍然只有一个

jobData
对象 - 结果是
AddJob()
将等待当前作业完成处理。这可能不是您想要的。也许您应该拥有
Queue<T>
的作业数据对象;
AddJob
Enqueue
一个项目,而
Run
会一直
Dequeue
' 直到队列为空。如果这样做,
Run
中的锁定语句应仅包含对队列的访问,而不是整个处理阶段。


0
投票

我不知道性能如何,但看起来你想要AutoResetEvent

这无疑为您提供了执行您所描述的操作的最简单方法之一。测试一下,如果您发现性能是一个问题,那么就考虑另一种方法来实现它。


0
投票

在我看来,您想使用生产者/消费者模式。使用阻塞队列最容易实现这一点。一旦你有了这个,那么其他一切就很容易了。您可以在here找到实现,也可以使用 4.0 中提供的 BlockingCollection 类。

注意:为简洁起见,省略了强化代码。

public class TheClass
{
    private Thread m_Thread;
    private BlockingCollection<object> m_Queue = new BlockingCollection<object>();
    private CancellationTokenSource m_Cancellation = new CancellationTokenSource();

    public void Start()
    {
        m_Thread = new Thread(new ThreadStart(Run));
        m_Thread.IsBackground = true;
        m_Thread.Start();
    }

    private void Run()
    {
        while (true)
        {
            try
            {
                object job = m_Queue.Take(m_Cancellation.Token);
            }
            catch (OperationCanceledException)
            {
                break;
            }
        }
    }

    public void AddJob(object param)
    {
        m_Queue.Add(param);
    }

    public void Stop()
    {
        m_Cancellation.Cancel();
        m_Thread.Join();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.