Rilevamento che un oggetto ThreadPool WorkItem è stato completato / in attesa di completamento
-
03-07-2019 - |
Domanda
Per qualsiasi motivo, il ThreadPool
QueueWorkItem
non restituisce un IAsyncResult
o qualche altro handle per l'elemento di lavoro, che consentirebbe attendere fino al completamento. Esistono metodi RegisterWait ...
, ma devi passare un WaitHandle
e la loro creazione è costosa (vedi la documentazione IAsyncResult
, che ti consiglia di ritardare la creazione di un WaitHandle
fino a quando richiesto). Task Parallel Library risolverà questa mancanza, ma c'è una lunga attesa prima che sia disponibile. Quindi, ci sono problemi con questo design:
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: Ho fatto una domanda di follow-up sui dubbi che si presentano quando si utilizzano delegati asincroni anziché ThreadPool .
Soluzione
Bene, hai una condizione di gara tra il recupero di WaitHandle e l'impostazione. Vuoi davvero che il chiamante stia aspettando per sempre se capita di essere un po 'in ritardo?
Probabilmente dovresti fare un blocco appropriato e mantenere un " Ho finito " in modo che se fai crei WaitHandle al termine, lo imposti prima di restituirlo.
Scriverei anche personalmente un metodo statico di fabbrica piuttosto che semplicemente usando un costruttore pubblico - o lo farei un " creare e quindi avviare esplicitamente " modello. Accodare l'oggetto di lavoro nel costruttore mi sembra strano.
Altri suggerimenti
Perché non stai usando un delegato asincrono, come mostrato qui:
http://msdn.microsoft.com/en-us/library /h80ttd5f.aspx
Ciò renderebbe Concurrent obsoleto, no?