Обнаружение того, что рабочий элемент ThreadPool завершен/ожидает завершения

StackOverflow https://stackoverflow.com/questions/405600

Вопрос

Для любой причины, ThreadPool's 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;
        }

    ...

РЕДАКТИРОВАТЬ:Я спросил дополнительный вопрос о проблемах, которые возникают при использовании асинхронных делегатов вместо ThreadPool.

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top