Там какой-либо путь состоит в том, чтобы заставить делегата работать на определенном потоке?
Скажите, что я имею:
CustomDelegate del = someObject.someFunction;
Thread dedicatedThread = ThreadList[x];
Я могу иметь последовательный фон длительный поток и вызвать моих собственных делегатов на него каждый раз, когда мне нужен он. Это должен быть тот же поток каждый раз.
[Править]
Причина, почему я хочу, чтобы это было на специализированном потоке, время, то, что я inten, чтобы выполнить делегата на нем и приостановить поток после y
миллисекунды и резюме поток, когда я выполняю другого делегата на нем. Я вижу, что это не возможно. Я буду иметь очередь делегата и позволю основной функции чтения потока и выполнения от него.
Для разъяснения с конкретным примером у меня есть игровая система с набором потоков плеера. Я хотел бы, чтобы каждый playerthread выполнил обработчики событий для игровых событий на нем. Если бы обработчики событий занимают слишком много времени, я хотел бы смочь приостановить тот конкретный плеер до следующего события путем приостановки его потока.
Таким образом имея специализированный поток, на котором я могу выполнить несколько обработчиков событий, я могу приостановить AI конкретного игрока в случае, если это стало с ошибками или занимает слишком много времени.
Я думаю, что лучшим решением будет использовать объекты Task
и поставить их в очередь в StaThreadScheduler , выполняющем один нить.
В качестве альтернативы можно использовать ActionThread
в Nito.Async для создания обычного потока со встроенной очередью делегатов Action
.
Однако ни один из них не решит напрямую другую потребность: возможность «приостановить» одно действие и продолжить другое. Для этого вам нужно разбрасывать «точки синхронизации» на каждое действие и иметь способ сохранить его состояние, повторно поставить его в очередь и продолжить выполнение следующего действия.
Вся эта сложность почти приближается к системе планирования потоков, поэтому я рекомендую сделать шаг назад и провести еще одну переделку. Вы можете поставить каждое действие в очередь на ThreadPool
(я рекомендую, чтобы каждое из них было только объектом Task
). Вам все равно нужно будет добавить «точки синхронизации», но вместо того, чтобы сохранять состояние и повторно ставить их в очередь, вам просто нужно приостановить (заблокировать) их.
Обычно я предлагаю просто использовать пул потоков или класс BackgroundWorker
, но это не гарантирует, что работа будет выполняться в каком-либо конкретном потоке. Непонятно, почему вам важно, какой поток выполняет работу, но если предположить, что это имеет какое-то значение ...
Вам придется передать объект Delegate
через какую-то разделяемую память, например, очередь. Фоновый поток должен будет следить за этой очередью, извлекать из нее делегатов, когда они существуют, и выполнять их.
Если окажется, что пул потоков подходит для выполнения вашего кода, вы всегда можете использовать для этого метод BeginInvoke
делегата:
// wrap your custom delegate in an action for simplicity ...
Action someCode = () => yourCustomDelegate( p1, p2, p3, ... );
// asynchronously execute the currying Action delegate on the threadpool...
someCode.BeginInvoke( someCode.EndInvoke, action );
К сожалению, на самом деле нет ничего встроенного для этого ни в одном универсальном потоке. Вы можете добиться этого, создав класс, который является оболочкой для Thread и реализует ISynchonizeInvoke.
Простым подходом является создание очереди обработки событий в выделенном потоке, как упоминает Л.Бушкин. Я предлагаю использовать класс Queue
и напрямую вызывать делегат Action. Вы можете выполнить большинство задач, которые вам могут понадобиться, с помощью действий анонимного делегата.
Наконец, в качестве предупреждения я предлагаю вам использовать Semaphore или EventWaitHandle вместо Thread.Sleep в вашем выделенном потоке. Это определенно более дружелюбно, чем повторять фоновый цикл снова и снова, когда в этом нет необходимости.
Для создаваемых вами потоков вы можете указать делегат ThreadStart только при их создании. Нет никаких условий для внедрения другого делегата в созданный поток. Пул потоков отличается тем, что позволяет отправлять делегатов в ранее созданные потоки, которые он запускает от вашего имени.
Непонятно, какую проблему вы пытаетесь решить. Чего вы пытаетесь достичь (или избежать), пытаясь запустить несколько делегатов в одном потоке?