다음을 통해 공유


ConcurrentDictionary<TKey,TValue>.AddOrUpdate 메서드

정의

키가 아직 없는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 추가하고, 키가 이미 있는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 업데이트합니다.

오버로드

AddOrUpdate(TKey, Func<TKey,TValue>, Func<TKey,TValue,TValue>)

지정된 함수를 사용하여 키가 아직 없는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 추가하고, 키가 이미 있는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 업데이트합니다.

AddOrUpdate(TKey, TValue, Func<TKey,TValue,TValue>)

키가 아직 없는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 추가하고, 키가 이미 있는 경우 지정된 함수를 사용하여 ConcurrentDictionary<TKey,TValue>의 키/값 쌍을 업데이트합니다.

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

지정된 함수와 인수를 사용하여 키가 아직 없는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 추가하고, 키가 이미 있는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 업데이트합니다.

예제

다음 예제에서는 메서드를 호출 AddOrUpdate 하는 방법을 보여줍니다.

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

AddOrUpdate(TKey, Func<TKey,TValue>, Func<TKey,TValue,TValue>)

Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs

지정된 함수를 사용하여 키가 아직 없는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 추가하고, 키가 이미 있는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 업데이트합니다.

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

매개 변수

key
TKey

추가하거나 값을 업데이트해야 하는 키입니다.

addValueFactory
Func<TKey,TValue>

없는 키에 대한 값을 생성하는 데 사용되는 함수입니다.

updateValueFactory
Func<TKey,TValue,TValue>

키의 기존 값을 기준으로 기존 키의 새 값을 생성하는 데 사용되는 함수입니다.

반환

TValue

키의 새 값입니다. addValueFactory가 발생(키가 없는 경우)하거나 updateValueFactory가 발생(키가 있는 경우)합니다.

예외

key, addValueFactory 또는 updateValueFactorynull입니다.

사전에 너무 많은 요소가 포함되어 있습니다.

설명

다른 스레드에서 동시에 를 호출 AddOrUpdate 하는 경우 는 addValueFactory 여러 번 호출될 수 있지만 해당 키/값 쌍은 모든 호출에 대해 사전에 추가되지 않을 수 있습니다.

사전에 대한 수정 및 쓰기 작업의 경우 는 ConcurrentDictionary<TKey,TValue> 세분화된 잠금을 사용하여 스레드 안전을 보장합니다(사전에 대한 읽기 작업은 잠금이 없는 방식으로 수행됨). addValueFactoryupdateValueFactory 대리자를 여러 번 실행하여 값이 예상대로 추가되거나 업데이트되었는지 확인할 수 있습니다. 그러나 잠금에서 알 수 없는 코드를 실행하여 발생할 수 있는 문제를 방지하기 위해 잠금 외부에서 호출됩니다. 따라서 는 AddOrUpdate 클래스의 다른 모든 연산 ConcurrentDictionary<TKey,TValue> 과 관련하여 원자적이지 않습니다.

추가 정보

적용 대상

AddOrUpdate(TKey, TValue, Func<TKey,TValue,TValue>)

Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs

키가 아직 없는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 추가하고, 키가 이미 있는 경우 지정된 함수를 사용하여 ConcurrentDictionary<TKey,TValue>의 키/값 쌍을 업데이트합니다.

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

매개 변수

key
TKey

추가하거나 값을 업데이트해야 하는 키입니다.

addValue
TValue

없는 키에 대해 추가할 값입니다.

updateValueFactory
Func<TKey,TValue,TValue>

키의 기존 값을 기준으로 기존 키의 새 값을 생성하는 데 사용되는 함수입니다.

반환

TValue

키의 새 값입니다. addValue가 발생(키가 없는 경우)하거나 updateValueFactory가 발생(키가 있는 경우)합니다.

예외

key 또는 updateValueFactorynull인 경우

사전에 너무 많은 요소가 포함되어 있습니다.

예제

다음 코드 예제에서는 를 초기화하는 ConcurrentDictionary<TKey,TValue> 방법과 AddOrUpdate 메서드를 사용하여 컬렉션에 항목을 추가하고 기존 항목을 업데이트하는 방법을 보여 줍니다.

using System;
using System.Collections.Concurrent;

class CD_Ctor
{
    // Demonstrates:
    //      ConcurrentDictionary<TKey, TValue> ctor(concurrencyLevel, initialCapacity)
    //      ConcurrentDictionary<TKey, TValue>[TKey]
    static void Main()
    {
        // We know how many items we want to insert into the ConcurrentDictionary.
        // So set the initial capacity to some prime number above that, to ensure that
        // the ConcurrentDictionary does not need to be resized while initializing it.
        int HIGHNUMBER = 64;
        int initialCapacity = 101;

        // The higher the concurrencyLevel, the higher the theoretical number of operations
        // that could be performed concurrently on the ConcurrentDictionary.  However, global
        // operations like resizing the dictionary take longer as the concurrencyLevel rises.
        // For the purposes of this example, we'll compromise at numCores * 2.
        int numProcs = Environment.ProcessorCount;
        int concurrencyLevel = numProcs * 2;

        // Construct the dictionary with the desired concurrencyLevel and initialCapacity
        ConcurrentDictionary<int, int> cd = new ConcurrentDictionary<int, int>(concurrencyLevel, initialCapacity);

        // Initialize the dictionary
        for (int i = 1; i <= HIGHNUMBER; i++) cd[i] = i * i;

        Console.WriteLine("The square of 23 is {0} (should be {1})", cd[23], 23 * 23);

        // Now iterate through, adding one to the end of the list. Existing items should be updated to be divided by their
        // key  and a new item will be added that is the square of its key.
        for (int i = 1; i <= HIGHNUMBER + 1; i++)
          cd.AddOrUpdate(i, i * i, (k,v) => v / i);

        Console.WriteLine("The square root of 529 is {0} (should be {1})", cd[23], 529 / 23);
        Console.WriteLine("The square of 65 is {0} (should be {1})", cd[HIGHNUMBER + 1], ((HIGHNUMBER + 1) * (HIGHNUMBER + 1)));
    }
}
open System
open System.Collections.Concurrent

// Demonstrates:
//      ConcurrentDictionary<TKey, TValue> ctor(concurrencyLevel, initialCapacity)
//      ConcurrentDictionary<TKey, TValue>[TKey]

// We know how many items we want to insert into the ConcurrentDictionary.
// So set the initial capacity to some prime number above that, to ensure that
// the ConcurrentDictionary does not need to be resized while initializing it.
let HIGHNUMBER = 64
let initialCapacity = 101

// The higher the concurrencyLevel, the higher the theoretical number of operations
// that could be performed concurrently on the ConcurrentDictionary.  However, global
// operations like resizing the dictionary take longer as the concurrencyLevel rises.
// For the purposes of this example, we'll compromise at numCores * 2.
let numProcs = Environment.ProcessorCount
let concurrencyLevel = numProcs * 2

// Construct the dictionary with the desired concurrencyLevel and initialCapacity
let cd = ConcurrentDictionary<int, int>(concurrencyLevel, initialCapacity)

// Initialize the dictionary
for i = 1 to HIGHNUMBER do
    cd[i] <- i * i

printfn $"The square of 23 is {cd[23]} (should be {23 * 23})"

// Now iterate through, adding one to the end of the list. Existing items should be updated to be divided by their
// key  and a new item will be added that is the square of its key.
for i = 1 to HIGHNUMBER + 1 do
    cd.AddOrUpdate(i, i * i, (fun k v -> v / i)) |> ignore

printfn $"The square root of 529 is {cd[23]} (should be {529 / 23})"
printfn $"The square of 65 is {cd[HIGHNUMBER + 1]} (should be {(HIGHNUMBER + 1) * (HIGHNUMBER + 1)})"
Imports System.Collections.Concurrent

Class CD_Ctor
    ' Demonstrates: 
    '      ConcurrentDictionary<TKey, TValue> ctor(concurrencyLevel, initialCapacity) 
    '      ConcurrentDictionary<TKey, TValue>[TKey] 
    Public Shared Sub Main()
        ' We know how many items we want to insert into the ConcurrentDictionary. 
        ' So set the initial capacity to some prime number above that, to ensure that 
        ' the ConcurrentDictionary does not need to be resized while initializing it. 
        Dim HIGHNUMBER As Integer = 64
        Dim initialCapacity As Integer = 101

        ' The higher the concurrencyLevel, the higher the theoretical number of operations 
        ' that could be performed concurrently on the ConcurrentDictionary.  However, global 
        ' operations like resizing the dictionary take longer as the concurrencyLevel rises.  
        ' For the purposes of this example, we'll compromise at numCores * 2. 
        Dim numProcs As Integer = Environment.ProcessorCount
        Dim concurrencyLevel As Integer = numProcs * 2

        ' Construct the dictionary with the desired concurrencyLevel and initialCapacity
        Dim cd As New ConcurrentDictionary(Of Integer, Integer)(concurrencyLevel, initialCapacity)

        ' Initialize the dictionary 
        For i As Integer = 1 To HIGHNUMBER
            cd(i) = i * i
        Next

        Console.WriteLine("The square of 23 is {0} (should be {1})", cd(23), 23 * 23)

        ' Now iterate through, adding one to the end of the list. Existing items should be updated to be divided by their 
        ' key  and a new item will be added that is the square of its key.
        For i As Integer = 1 To HIGHNUMBER + 1

            cd.AddOrUpdate(i, i * i, Function(k, v)
                                         Return v / i
                                     End Function)
        Next

        Console.WriteLine("The square root of 529 is {0} (should be {1})", cd(23), 529 / 23)
        Console.WriteLine("The square of 65 is {0} (should be {1})", cd(HIGHNUMBER + 1), ((HIGHNUMBER + 1) * (HIGHNUMBER + 1)))

    End Sub
End Class

사전에 대한 수정 및 쓰기 작업의 경우 는 ConcurrentDictionary<TKey,TValue> 세분화된 잠금을 사용하여 스레드 안전을 보장합니다. (사전에 대한 읽기 작업은 잠금이 없는 방식으로 수행됩니다.) addValueFactoryupdateValueFactory 대리자를 여러 번 실행하여 값이 예상대로 추가되거나 업데이트되었는지 확인할 수 있습니다. 그러나 잠금에서 알 수 없는 코드를 실행하여 발생할 수 있는 문제를 방지하기 위해 잠금 외부에서 호출됩니다. 따라서 는 AddOrUpdate 클래스의 다른 모든 연산 ConcurrentDictionary<TKey,TValue> 과 관련하여 원자적이지 않습니다.

추가 정보

적용 대상

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

Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs

지정된 함수와 인수를 사용하여 키가 아직 없는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 추가하고, 키가 이미 있는 경우 ConcurrentDictionary<TKey,TValue>에 키/값 쌍을 업데이트합니다.

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

형식 매개 변수

TArg

updateValueFactory에 전달할 addValueFactory 인수의 형식입니다.

매개 변수

key
TKey

추가하거나 값을 업데이트해야 하는 키입니다.

addValueFactory
Func<TKey,TArg,TValue>

없는 키에 대한 값을 생성하는 데 사용되는 함수입니다.

updateValueFactory
Func<TKey,TValue,TArg,TValue>

키의 기존 값을 기준으로 기존 키의 새 값을 생성하는 데 사용되는 함수입니다.

factoryArgument
TArg

addValueFactoryupdateValueFactory에 전달할 인수입니다.

반환

TValue

키의 새 값입니다. addValueFactory가 발생(키가 없는 경우)하거나 updateValueFactory가 발생(키가 있는 경우)합니다.

예외

key, addValueFactory 또는 updateValueFactory가 null 참조(Visual Basic의 경우 Nothing)인 경우

사전에 너무 많은 요소가 포함되어 있습니다.

설명

다른 스레드에서 동시에 를 호출 AddOrUpdate 하는 경우 는 addValueFactory 여러 번 호출될 수 있지만 해당 키/값 쌍은 모든 호출에 대해 사전에 추가되지 않을 수 있습니다.

사전에 대한 수정 및 쓰기 작업의 경우 는 ConcurrentDictionary<TKey,TValue> 세분화된 잠금을 사용하여 스레드 안전을 보장합니다. (사전에 대한 읽기 작업은 잠금이 없는 방식으로 수행됩니다.) addValueFactoryupdateValueFactory 대리자를 여러 번 실행하여 값이 예상대로 추가되거나 업데이트되었는지 확인할 수 있습니다. 그러나 잠금에서 알 수 없는 코드를 실행하여 발생할 수 있는 문제를 방지하기 위해 잠금 외부에서 호출됩니다. 따라서 는 AddOrUpdate 클래스의 다른 모든 연산 ConcurrentDictionary<TKey,TValue> 과 관련하여 원자적이지 않습니다.

적용 대상