Pergunta

Por alguma razão, ThreadPool de QueueWorkItem não retorna um IAsyncResult ou algum outro identificador para o item de trabalho, o que permitiria que esperar até que seja concluída. Existem métodos RegisterWait..., mas você tem que passar por um WaitHandle e criá-los é caro (consulte a documentação IAsyncResult, que aconselha a atrasar a criação de um WaitHandle até solicitado). A biblioteca paralela de tarefas irá corrigir essa falta, mas há uma longa espera antes que está disponível. Então, existem problemas com este projeto:

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: Perguntei a um follow-up questão sobre as preocupações que surgem quando se utiliza delegados assíncronos em vez do ThreadPool .

Foi útil?

Solução

Bem, você tem uma condição de corrida entre buscar o WaitHandle e defini-lo. Você realmente quer o chamador para ser esperando para sempre, se acontecer de ser um pouco tarde?

Você provavelmente deve fazer algum bloqueio apropriado e manter uma bandeira "Eu terminei", de modo que se você do criar o WaitHandle depois que terminar, você configurá-lo antes de devolvê-lo.

Eu também, pessoalmente, escrever um método de fábrica estático em vez de apenas usando um construtor público - ou torná-lo um "criar e então explicitamente iniciar" padrão. Enfileiramento o item de trabalho no construtor sente estranho para mim.

Outras dicas

Por que você não está usando um delegado assíncrona, como demostrated aqui:

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

Isso faria Concurrent obsoleto, não?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top