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>)

來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
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 (如果索引鍵存在) 的結果。

例外狀況

keyaddValueFactoryupdateValueFactorynull

目錄包含太多項目。

備註

如果您在不同的線程上同時呼叫 AddOrUpdateaddValueFactory 可能會多次呼叫,但其索引鍵/值組可能不會新增至每個呼叫的字典。

如需對字典的修改和寫入作業, ConcurrentDictionary<TKey,TValue> 請使用精細鎖定來確保字典上的線程安全 (讀取作業是以無鎖定的方式執行) 。 addValueFactoryupdateValueFactory 委派可以多次執行,以確認值已如預期新增或更新。 不過,它們會在鎖定外部呼叫,以避免在鎖定下執行未知程式代碼時可能發生的問題。 因此, AddOrUpdate 對於類別上所有其他作業而言,不是不可部分完成的 ConcurrentDictionary<TKey,TValue>

另請參閱

適用於

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

來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
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 (如果索引鍵存在) 的結果。

例外狀況

keyupdateValueFactorynull

目錄包含太多項目。

範例

下列程式代碼範例示範如何初始化 , 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)

來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
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

要傳入 addValueFactory 和的自變數型別 updateValueFactory

參數

key
TKey

要新增或應該更新其值的索引鍵。

addValueFactory
Func<TKey,TArg,TValue>

用來為不存在之索引鍵產生值的函式。

updateValueFactory
Func<TKey,TValue,TArg,TValue>

用來根據索引鍵之現有值為現有索引鍵產生新值的函式。

factoryArgument
TArg

要傳入 addValueFactoryupdateValueFactory 的引數。

傳回

TValue

索引鍵的新值。 這個值會是 addValueFactory (如果索引鍵不存在) 的結果或 updateValueFactory (如果索引鍵存在) 的結果。

例外狀況

keyaddValueFactoryupdateValueFactory 為 Null 參考 (在 Visual Basic 中為 Nothing)。

目錄包含太多項目。

備註

如果您在不同的線程上同時呼叫 AddOrUpdateaddValueFactory 可能會多次呼叫,但其索引鍵/值組可能不會新增至每個呼叫的字典。

如需對字典的修改和寫入作業, ConcurrentDictionary<TKey,TValue> 請使用精細鎖定來確保線程安全。 (字典上的讀取作業是以無鎖定的方式執行。) addValueFactoryupdateValueFactory 委派可能會多次執行,以確認值已如預期新增或更新。 不過,它們會在鎖定外部呼叫,以避免在鎖定下執行未知程式代碼時可能發生的問題。 因此, AddOrUpdate 對於類別上所有其他作業而言,不是不可部分完成的 ConcurrentDictionary<TKey,TValue>

適用於