сигнализирующий о спящем потоке - PullRequest
1 голос
/ 15 августа 2010

Я новичок в многопоточности в 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
    }
}

в этом классе, какой самый эффективный метод для получения закомментированных фраз и для общей производительности?

Ответы [ 3 ]

2 голосов
/ 15 августа 2010

Рассмотрите возможность использования 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 голосов
/ 15 августа 2010

Мне кажется, что вы хотите использовать шаблон «производитель / потребитель».Это легче всего сделать, используя очередь блокировки.Если у вас есть это, все остальное легко.Вы можете найти реализацию здесь или использовать класс BlockingCollection , доступный в версии 4.0.

Примечание. Код жесткости для краткости опущен.

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();
    }
}
0 голосов
/ 15 августа 2010

Я не знаю о производительности, но похоже, что вы хотите AutoResetEvent .

Это, безусловно, дает вам один из самых простых способов сделать то, что вы описываете.Проверьте это, и если вы обнаружите, что производительность представляет собой проблему, то позаботьтесь о другом способе сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...