Реализация очереди потока - PullRequest
1 голос
/ 11 февраля 2012

Рассмотрим этот пример: когда пользователь нажимает кнопку, ClassA запускает событие OnUserInteraction быстро 10 раз.ClassB присоединено к этому событию и в своем обработчике события запускает метод Render ClassC.В методе Render выполняется AxisAngleRotation3D, но каждая анимация длится 1 секунду.

В этом сценарии все анимации 10 AxisAngleRotation3D выполняются практически одновременно, но я бы хотел, чтобы они выполнялись одна за другой.Как я понимаю потоки, мне, вероятно, придется реализовать очередь потоков в ClassB, где событие Completed из AxisAngleRotation3D сигнализирует о том, что следующее событие разрешено запускать ...это правильно и как мне этого добиться?

Ответы [ 2 ]

3 голосов
/ 11 февраля 2012

Есть очередь задач.Проще говоря, имейте поле ConcurrentQueue<Func<bool>> или подобное, и добавляйте к нему задачи по мере необходимости.Затем попросите поток выполнения задачи выдать Func<bool> делегатов из очереди и вызвать их.Если они вернут истину, они сделали.Если они возвращают false, добавьте их обратно в очередь, поскольку они не могли завершиться в это время.

Вот пример:

using System;
using System.Collections.Concurrent;
using System.Threading;

namespace Example
{
    public class TaskScheduler : IDisposable
    {
        public const int IDLE_DELAY = 100;

        private ConcurrentQueue<Func<bool>> PendingTasks;
        private Thread ExecuterThread;
        private volatile bool _IsDisposed;

        public bool IsDisposed
        {
            get { return _IsDisposed; }
        }

        public void EnqueueTask(Func<bool> task)
        {
            PendingTasks.Enqueue(task);
        }

        public void Start()
        {
            CheckDisposed();

            if (ExecuterThread != null)
            {
                throw new InvalidOperationException("The task scheduler is alreader running.");
            }

            ExecuterThread = new Thread(Run);
            ExecuterThread.IsBackground = true;
            ExecuterThread.Start();
        }

        private void CheckDisposed()
        {
            if (_IsDisposed)
            {
                throw new ObjectDisposedException("TaskScheduler");
            }
        }

        private void Run()
        {
            while (!_IsDisposed)
            {
                if (PendingTasks.IsEmpty)
                {
                    Thread.Sleep(IDLE_DELAY);
                    continue;
                }

                Func<bool> task;
                while (!PendingTasks.TryDequeue(out task))
                {
                    Thread.Sleep(0);
                }

                if (!task.Invoke())
                {
                    PendingTasks.Enqueue(task);
                }
            }
        }

        public void Dispose()
        {
            CheckDisposed();
            _IsDisposed = true;
        }
    }
}
3 голосов
/ 11 февраля 2012

ClassB может добавить событие в очередь, а затем отобразить их по одному (возможно, использовать таймер для чтения из очереди).

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