Condividi tramite


ConcurrentDictionary<TKey,TValue>.GetOrAdd Metodo

Definizione

Aggiunge una coppia chiave/valore a ConcurrentDictionary<TKey,TValue> se la chiave non esiste già. Restituisce il nuovo valore, oppure, se la chiave esiste già, restituisce il valore esistente.

Overload

GetOrAdd(TKey, Func<TKey,TValue>)

Aggiunge una coppia chiave/valore a ConcurrentDictionary<TKey,TValue> usando la funzione specificata se la chiave non esiste già. Restituisce il nuovo valore, oppure, se la chiave esiste, restituisce il valore esistente.

GetOrAdd(TKey, TValue)

Aggiunge una coppia chiave/valore a ConcurrentDictionary<TKey,TValue> se la chiave non esiste già. Restituisce il nuovo valore, oppure, se la chiave esiste, restituisce il valore esistente.

GetOrAdd<TArg>(TKey, Func<TKey,TArg,TValue>, TArg)

Aggiunge una coppia chiave/valore a ConcurrentDictionary<TKey,TValue> usando la funzione specificata e un argomento se la chiave non esiste ancora, oppure, se la chiave esiste già, restituisce il valore esistente.

Esempio

Nell'esempio seguente viene illustrato come chiamare il GetOrAdd metodo :

class CD_GetOrAddOrUpdate
{
    // Demonstrates:
    //      ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
    //      ConcurrentDictionary<TKey, TValue>.GetOrAdd()
    //      ConcurrentDictionary<TKey, TValue>[]
    static void Main()
    {
        // Construct a ConcurrentDictionary
        ConcurrentDictionary<int, int> cd = new ConcurrentDictionary<int, int>();

        // Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
        Parallel.For(0, 10000, i =>
        {
            // Initial call will set cd[1] = 1.
            // Ensuing calls will set cd[1] = cd[1] + 1
            cd.AddOrUpdate(1, 1, (key, oldValue) => oldValue + 1);
        });

        Console.WriteLine("After 10000 AddOrUpdates, cd[1] = {0}, should be 10000", cd[1]);

        // Should return 100, as key 2 is not yet in the dictionary
        int value = cd.GetOrAdd(2, (key) => 100);
        Console.WriteLine("After initial GetOrAdd, cd[2] = {0} (should be 100)", value);

        // Should return 100, as key 2 is already set to that value
        value = cd.GetOrAdd(2, 10000);
        Console.WriteLine("After second GetOrAdd, cd[2] = {0} (should be 100)", value);
    }
}
// Demonstrates:
//      ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
//      ConcurrentDictionary<TKey, TValue>.GetOrAdd()
//      ConcurrentDictionary<TKey, TValue>[]

// Construct a ConcurrentDictionary
let cd = ConcurrentDictionary<int, int>()

// Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
Parallel.For(
    0,
    10000,
    fun i ->

        // Initial call will set cd[1] = 1.
        // Ensuing calls will set cd[1] = cd[1] + 1
        cd.AddOrUpdate(1, 1, (fun key oldValue -> oldValue + 1)) |> ignore
)
|> ignore

printfn $"After 10000 AddOrUpdates, cd[1] = {cd[1]}, should be 10000"

// Should return 100, as key 2 is not yet in the dictionary
let value = cd.GetOrAdd(2, (fun key -> 100))
printfn $"After initial GetOrAdd, cd[2] = {value} (should be 100)"

// Should return 100, as key 2 is already set to that value2
let value2 = cd.GetOrAdd(2, 10000)
printfn $"After second GetOrAdd, cd[2] = {value2} (should be 100)"
' Imports System.Collections.Concurrent
' Imports System.Threading.Tasks

Class CD_GetOrAddOrUpdate

    ' Demonstrates:
    ' ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
    ' ConcurrentDictionary<TKey, TValue>.GetOrAdd()
    ' ConcurrentDictionary<TKey, TValue>[]
    Shared Sub Main()
        ' Construct a ConcurrentDictionary
        Dim cd As New ConcurrentDictionary(Of Integer, Integer)()

        ' Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
        Parallel.For(0, 10000,
                       Sub(i)
                           ' Initial call will set cd[1] = 1. 
                           ' Ensuing calls will set cd[1] = cd[1] + 1
                           cd.AddOrUpdate(1, 1, Function(key, oldValue) oldValue + 1)
                       End Sub)

        Console.WriteLine("After 10000 AddOrUpdates, cd[1] = {0}, should be 10000", cd(1))

        ' Should return 100, as key 2 is not yet in the dictionary
        Dim value As Integer = cd.GetOrAdd(2, Function(key) 100)
        Console.WriteLine("After initial GetOrAdd, cd[2] = {0} (should be 100)", value)

        ' Should return 100, as key 2 is already set to that value
        value = cd.GetOrAdd(2, 10000)
        Console.WriteLine("After second GetOrAdd, cd[2] = {0} (should be 100)", value)
    End Sub
End Class

GetOrAdd(TKey, Func<TKey,TValue>)

Origine:
ConcurrentDictionary.cs
Origine:
ConcurrentDictionary.cs
Origine:
ConcurrentDictionary.cs

Aggiunge una coppia chiave/valore a ConcurrentDictionary<TKey,TValue> usando la funzione specificata se la chiave non esiste già. Restituisce il nuovo valore, oppure, se la chiave esiste, restituisce il valore esistente.

public:
 TValue GetOrAdd(TKey key, Func<TKey, TValue> ^ valueFactory);
public TValue GetOrAdd (TKey key, Func<TKey,TValue> valueFactory);
member this.GetOrAdd : 'Key * Func<'Key, 'Value> -> 'Value
Public Function GetOrAdd (key As TKey, valueFactory As Func(Of TKey, TValue)) As TValue

Parametri

key
TKey

Chiave dell'elemento da aggiungere.

valueFactory
Func<TKey,TValue>

Funzione usata per generare un valore per la chiave.

Restituisce

TValue

Valore della chiave. Si tratta del valore esistente se la chiave esiste già nel dizionario o del nuovo valore se la chiave non è presente nel dizionario.

Eccezioni

key o valueFactory è null.

Il dizionario contiene troppi elementi.

Commenti

Per le modifiche e le operazioni di scrittura nel dizionario, ConcurrentDictionary<TKey,TValue> usa il blocco con granularità fine per garantire la thread safety. Le operazioni di lettura nel dizionario vengono eseguite in modo senza blocco. Tuttavia, il valueFactory delegato viene chiamato all'esterno dei blocchi per evitare i problemi che possono verificarsi dall'esecuzione di codice sconosciuto in un blocco. Pertanto, GetOrAdd non è atomico per quanto riguarda tutte le altre operazioni sulla ConcurrentDictionary<TKey,TValue> classe .

Poiché un valore/chiave può essere inserito da un altro thread durante valueFactory la generazione di un valore, non è possibile considerare attendibile che solo perché valueFactory eseguito, il relativo valore generato verrà inserito nel dizionario e restituito. Se si chiama GetOrAdd contemporaneamente su thread diversi, valueFactory può essere chiamato più volte, ma al dizionario verrà aggiunta una sola coppia chiave/valore.

Il valore restituito dipende dalla presenza della chiave nel dizionario e dall'inserimento di una chiave/valore da un altro thread dopo GetOrAdd la chiamata, ma prima di valueFactory generare un valore:

Scenario Valore restituito
La chiave è già presente nel dizionario. Viene restituito il valore esistente.
La chiave non è presente nel dizionario. valueFactory genera un valore. Quando si ricontrolla per la chiave, non viene trovata alcuna chiave. La chiave/valore viene inserita nel dizionario e il valore viene restituito.
La chiave non è presente nel dizionario. valueFactory genera un valore. Durante valueFactory la generazione del valore, un thread diverso inserisce un valore per la chiave. Dopo valueFactory l'esecuzione e la verifica della chiave, viene trovata la chiave inserita dall'altro thread. Viene restituito il valore inserito dall'altro thread.

Vedi anche

Si applica a

GetOrAdd(TKey, TValue)

Origine:
ConcurrentDictionary.cs
Origine:
ConcurrentDictionary.cs
Origine:
ConcurrentDictionary.cs

Aggiunge una coppia chiave/valore a ConcurrentDictionary<TKey,TValue> se la chiave non esiste già. Restituisce il nuovo valore, oppure, se la chiave esiste, restituisce il valore esistente.

public:
 TValue GetOrAdd(TKey key, TValue value);
public TValue GetOrAdd (TKey key, TValue value);
member this.GetOrAdd : 'Key * 'Value -> 'Value
Public Function GetOrAdd (key As TKey, value As TValue) As TValue

Parametri

key
TKey

Chiave dell'elemento da aggiungere.

value
TValue

Valore da aggiungere, se la chiave non esiste ancora.

Restituisce

TValue

Valore della chiave. Si tratta del valore esistente se la chiave esiste già nel dizionario o del nuovo valore se la chiave non è presente nel dizionario.

Eccezioni

key è null.

Il dizionario contiene troppi elementi.

Vedi anche

Si applica a

GetOrAdd<TArg>(TKey, Func<TKey,TArg,TValue>, TArg)

Origine:
ConcurrentDictionary.cs
Origine:
ConcurrentDictionary.cs
Origine:
ConcurrentDictionary.cs

Aggiunge una coppia chiave/valore a ConcurrentDictionary<TKey,TValue> usando la funzione specificata e un argomento se la chiave non esiste ancora, oppure, se la chiave esiste già, restituisce il valore esistente.

public:
generic <typename TArg>
 TValue GetOrAdd(TKey key, Func<TKey, TArg, TValue> ^ valueFactory, TArg factoryArgument);
public TValue GetOrAdd<TArg> (TKey key, Func<TKey,TArg,TValue> valueFactory, TArg factoryArgument);
member this.GetOrAdd : 'Key * Func<'Key, 'Arg, 'Value> * 'Arg -> 'Value
Public Function GetOrAdd(Of TArg) (key As TKey, valueFactory As Func(Of TKey, TArg, TValue), factoryArgument As TArg) As TValue

Parametri di tipo

TArg

Tipo di un argomento da passare in valueFactory.

Parametri

key
TKey

Chiave dell'elemento da aggiungere.

valueFactory
Func<TKey,TArg,TValue>

Funzione usata per generare un valore per la chiave.

factoryArgument
TArg

Valore dell'argomento da passare in valueFactory.

Restituisce

TValue

Valore della chiave. Si tratta del valore esistente se la chiave esiste già nel dizionario o del nuovo valore se la chiave non è presente nel dizionario.

Eccezioni

key è un riferimento null (Nothing in Visual Basic).

Il dizionario contiene troppi elementi.

Commenti

Per le modifiche e le operazioni di scrittura nel dizionario, ConcurrentDictionary<TKey,TValue> usa il blocco con granularità fine per garantire la thread safety. Le operazioni di lettura nel dizionario vengono eseguite in modo senza blocco. Tuttavia, il valueFactory delegato viene chiamato all'esterno dei blocchi per evitare i problemi che possono verificarsi dall'esecuzione di codice sconosciuto in un blocco. Pertanto, GetOrAdd non è atomico per quanto riguarda tutte le altre operazioni sulla ConcurrentDictionary<TKey,TValue> classe .

Poiché un valore/chiave può essere inserito da un altro thread durante valueFactory la generazione di un valore, non è possibile considerare attendibile che solo perché valueFactory eseguito, il relativo valore generato verrà inserito nel dizionario e restituito. Se si chiama GetOrAdd contemporaneamente su thread diversi, valueFactory può essere chiamato più volte, ma al dizionario verrà aggiunta una sola coppia chiave/valore.

Il valore restituito dipende dalla presenza della chiave nel dizionario e dall'inserimento di una chiave/valore da un altro thread dopo GetOrAdd la chiamata, ma prima di valueFactory generare un valore:

Scenario Valore restituito
La chiave è già presente nel dizionario. Viene restituito il valore esistente.
La chiave non è presente nel dizionario. valueFactory genera un valore. Quando si ricontrolla per la chiave, non viene trovata alcuna chiave. La chiave/valore viene inserita nel dizionario e il valore viene restituito.
La chiave non è presente nel dizionario. valueFactory genera un valore. Durante valueFactory la generazione del valore, un thread diverso inserisce un valore per la chiave. Dopo valueFactory l'esecuzione e la verifica della chiave, viene trovata la chiave inserita dall'altro thread. Viene restituito il valore inserito dall'altro thread.

Si applica a