Nella mia app due componenti A e B, hanno i loro dati e stato in base ai dati e allo stato di un terzo componente, componente C:
- Sia A che B possono modificare i dati del componente C.
- Sia A che B ascoltano il cambiamento dei dati del componente C e reagiscono a rielaborando i dati e lo stato interni.
- A e B vengono eseguiti ciascuno sul proprio thread.
Ciò di cui sto cercando di implementare lo scenario in cui entrambi i componenti A e B cercano di aggiornare C simultaneamente e come reagire alle modifiche mentre l'operazione è in corso:
- A inizia ad aggiornare i dati su C
- B inizia ad aggiornare i dati su C. C ha un blocco interno che impedisce l'aggiornamento simultaneo dei dati, quindi l'operazione deve attendere che A venga completato per primo.
- A termina l'aggiornamento dei dati su C. C invia l'evento di modifica dei dati a entrambi A e B.
- B potrebbe iniziare ad aggiornare i dati su C, ma a questo punto i dati in C sono in uno stato diverso da come era quando B ha iniziato l'operazione. L'operazione potrebbe non avere più senso ora.
Nel passaggio n. 3, dove B ha ricevuto l'evento da C, penso che B dovrebbe rivalutare se stesso, ha bisogno di ricalcolare i suoi dati e lo stato. Ma dovrebbe anche cancellare la sua operazione di modifica dei dati avviata al punto # 2.
La stessa situazione può succedere il contrario, il componente B può iniziare prima l'operazione e il componente A è il secondo.
Questa è la parte con cui sto lottando, come implementare tutto questo. Prima di parlare di codice, darò anche un esempio più concreto:
L'interfaccia utente mostra un elemento su uno schermo che l'utente può aggiornare. C'è un componente in esecuzione su un thread in background, che può aggiornare lo stesso elemento a causa della modifica della posizione del dispositivo. Sia l'interfaccia utente che i componenti di localizzazione accedono al repository degli articoli, per aggiornare l'articolo.
Sto cercando alcuni suggerimenti su come implementarlo.
Uso .NET C #, quindi la mia soluzione utilizza classi specifiche per .NET. Tuttavia, non volevo rendere questa domanda specifica a .NET, perché la stessa domanda potrebbe applicarsi anche a Java e ad altre lingue \ tecnologie.
Un'idea che ho è che sia l'interfaccia utente sia il monitoraggio della posizione mantengano ciascuno un CancellationTokenSource
che possono cancellare quando ricevono l'evento da C:
CancellationTokenSource _cts;
void UpdateItem(Item item) {
_cts = new CancellationTokenSource();
try
{
_itemRepo.UpdateItem(item, …, _cts.Token);
}
catch(OperationCancelled)
{
// re-evaluate state here
}
}
void ItemRepo_DataChanged(object sender, EventArgs e)
{
if(_cts != null) {
_cts.Cancel();
}
}
Vedi altri modi per implementarlo?
In alternativa, ci sono esempi in framework o strumenti o anche progetti OSS che potrei dare un'occhiata?