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>
Функция, используемая для создания нового значения для существующего ключа на основе его текущего значения.
Возвращаемое значение
Новое значение для ключа. Это значение будет либо значением функции addValueFactory
(если ключ отсутствовал), либо результатом выполнения функции updateValueFactory
(если ключ присутствовал).
Исключения
Значение параметра key
, addValueFactory
или updateValueFactory
равно null
.
Словарь содержит слишком много элементов.
Комментарии
При одновременном вызове AddOrUpdate в разных потоках addValueFactory
может вызываться несколько раз, но его пара "ключ-значение" может не добавляться в словарь для каждого вызова.
Для операций изменения и записи в словарь использует детализированную блокировку, ConcurrentDictionary<TKey,TValue> чтобы обеспечить потокобезопасность (операции чтения в словаре выполняются без блокировки). Делегаты addValueFactory
и updateValueFactory
могут выполняться несколько раз, чтобы убедиться, что значение было добавлено или обновлено должным образом. Однако они вызываются вне блокировок, чтобы избежать проблем, которые могут возникнуть при выполнении неизвестного кода под блокировкой. Таким образом, AddOrUpdate не является атомарным по отношению ко всем остальным операциям в ConcurrentDictionary<TKey,TValue> классе .
См. также раздел
- Потокобезопасные коллекции
- Практическое руководство. Добавление элементов в коллекцию ConcurrentDictionary и их удаление из этой коллекции
Применяется к
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>
Функция, используемая для создания нового значения для существующего ключа на основе его текущего значения.
Возвращаемое значение
Новое значение для ключа. Это значение будет либо значением функции addValue
(если ключ отсутствовал), либо результатом выполнения функции updateValueFactory
(если ключ присутствовал).
Исключения
Параметр key
или updateValueFactory
имеет значение null
.
Словарь содержит слишком много элементов.
Примеры
В следующем примере кода показано, как инициализировать 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> обеспечения потокобезопасности. (Операции чтения в словаре выполняются без блокировки.) Делегаты addValueFactory
и updateValueFactory
могут выполняться несколько раз, чтобы убедиться, что значение было добавлено или обновлено должным образом. Однако они вызываются вне блокировок, чтобы избежать проблем, которые могут возникнуть при выполнении неизвестного кода под блокировкой. Таким образом, AddOrUpdate не является атомарным по отношению ко всем остальным операциям в ConcurrentDictionary<TKey,TValue> классе .
См. также раздел
- Потокобезопасные коллекции
- Практическое руководство. Добавление элементов в коллекцию ConcurrentDictionary и их удаление из этой коллекции
Применяется к
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
Аргумент, передаваемый в addValueFactory
и updateValueFactory
.
Возвращаемое значение
Новое значение для ключа. Это значение будет либо значением функции addValueFactory
(если ключ отсутствовал), либо результатом выполнения функции updateValueFactory
(если ключ присутствовал).
Исключения
key
, addValueFactory
или updateValueFactory
является ссылкой на NULL (Nothing в Visual Basic).
Словарь содержит слишком много элементов.
Комментарии
При одновременном вызове AddOrUpdate в разных потоках addValueFactory
может вызываться несколько раз, но его пара "ключ-значение" может не добавляться в словарь для каждого вызова.
Для операций изменения и записи в словарь использует детализированную блокировку для ConcurrentDictionary<TKey,TValue> обеспечения потокобезопасности. (Операции чтения в словаре выполняются без блокировки.) Делегаты addValueFactory
и updateValueFactory
могут выполняться несколько раз, чтобы убедиться, что значение было добавлено или обновлено должным образом. Однако они вызываются вне блокировок, чтобы избежать проблем, которые могут возникнуть при выполнении неизвестного кода под блокировкой. Таким образом, AddOrUpdate не является атомарным по отношению ко всем остальным операциям в ConcurrentDictionary<TKey,TValue> классе .