Обнаружение того, что WorkItem ThreadPool завершил / ожидает завершения - PullRequest
4 голосов
/ 02 января 2009

По какой-либо причине ThreadPool QueueWorkItem не возвращает IAsyncResult или какой-либо другой дескриптор для рабочего элемента, что позволило бы дождаться его завершения. Существуют RegisterWait... методы, но вы должны передать WaitHandle, а их создание стоит дорого (см. Документацию IAsyncResult, которая рекомендует отложить создание WaitHandle до запроса). Библиотека параллельных заданий исправит этот недостаток, но есть много времени, прежде чем он станет доступен. Итак, есть ли проблемы с этим дизайном:

public class Concurrent<T> {
    private ManualResetEvent _resetEvent;
    private T _result;

    public Concurrent(Func<T> f) {
        ThreadPool.QueueUserWorkItem(_ => {
                                         _result = f();
                                         if (_resetEvent != null)
                                             _resetEvent.Set();
                                     });
    }

    public WaitHandle WaitHandle {
        get {
            if (_resetEvent == null)
                _resetEvent = new ManualResetEvent(_result != null);
            return _resetEvent;
        }

    ...

EDIT: Я задал дополнительный вопрос о проблемах, возникающих при использовании асинхронных делегатов вместо ThreadPool .

Ответы [ 2 ]

6 голосов
/ 02 января 2009

Ну, у вас есть условие гонки между получением WaitHandle и его установкой. Вы действительно хотите, чтобы вызывающий абонент ждал вечно, если он опаздывает?

Вы, вероятно, должны сделать соответствующую блокировку и сохранить флаг "Я закончил", чтобы, если вы делаете создали WaitHandle после его завершения, вы установили его перед возвратом.

Я бы также лично написал метод статической фабрики, а не просто использовал открытый конструктор - или сделал бы его шаблоном «создать и , а затем явно запустить». Очередь рабочего элемента в конструкторе кажется мне странной.

3 голосов
/ 02 января 2009

Почему вы не используете асинхронный делегат, как показано ниже:

http://msdn.microsoft.com/en-us/library/h80ttd5f.aspx

Это сделало бы одновременное устаревание, нет?

...