Possiedo un servizio che garantisce che venga visualizzato esattamente un solo popup allo stesso tempo. AddPopupAsync
può essere chiamato contemporaneamente, vale a dire un popup è aperta, mentre un altro 10 AddPopupAsync
richieste cadono nel codice:.Come rendere i metodi asincroni che utilizzano un thread safe code
public async Task<int> AddPopupAsync(Message message)
{
//[...]
while (popupQueue.Count != 0)
{
await popupQueue.Peek();
}
return await Popup(interaction);
}
ma posso macchiare due cose indesiderate che possono accadere a causa della mancanza di sicurezza dei thread:
- Se la coda è vuota, Peek sarà un'eccezione
- Se un thread a è preempted prima della prima istruzione in popup, un altro thread B non attendere la comparsa in attesa un dato che la coda è ancora vuota.
metodo Popup funziona con un TaskCompletionSource
e prima di chiamare il suo metodo SetResult
, popupQueue.Dequeue()
si chiama.
Penso utilizzando l'atomica TryPeek
da ConcurrentQueue
al fine di rendere # 1 thread-safe:
do
{
Task<int> result;
bool success = popupQueue.TryPeek(out result);
if (!success) break;
await result;
}
while (true);
Poi ho letto di un AsyncProducerConsumerCollection ma non sono sicuro se questa è la soluzione più semplice.
Come si può garantire la sicurezza del filo in modo semplice? Grazie.
Penso che tu abbia risposto alla tua stessa domanda. 'ConcurrentQueue' ha ciò che è necessario integrato. –
La tua semantica corrente è che tutte le chiamate a 'AddPopupAsync' non verranno completate fino a quando non verranno visualizzati tutti i popup (non solo quello mostrato da quella particolare chiamata). Sei sicuro che sia la semantica che vuoi? –
@Stephen Cleary Poichè PopupView e PopupViewModel sono singleton, lo stato della finestra popup modale viene modificato ogni volta che viene richiamato Popup. Ed è per questo che sto usando una coda. – user4287276