TryTake крадет элемент, который был добавлен совсем недавно в другом потоке.C#

Место общения программистов C#
Ответить
Anonymous
 TryTake крадет элемент, который был добавлен совсем недавно в другом потоке.

Сообщение Anonymous »

При объяснении ConcurrentBag в онлайн-ссылке говорится, что:

... Итак, если быть точным, вызов Take отображает элемент, добавленный
последним образом в этом потоке; если в этом потоке нет элементов, он
дает вам элемент, добавленный последним в другом потоке, выбранный
случайно.

На самом деле, в VS, если вы в глубине души, вы увидите этот комментарий к методу TrySteal( внутренне вызывает этот метод):

Если для этого потока нет локальной очереди, просто начните с головной
очереди и попробуйте воровать из каждой очереди, пока не получим результат. Если из этого потока
есть локальная очередь, то начните со следующей очереди
после нее, а затем выполните итерацию от головы до этой очереди,
не включая ее.

Теперь позвольте мне показать вам следующую программу:

Код: Выделить всё

using static System.Console;
using System.Collections.Concurrent;

IProducerConsumerCollection cars = new ConcurrentBag();

var addBlackCars = Task.Run(ProcessBlackCarModels);
var addNonBlackCars = Task.Run(ProcessNonBlackCarModels);
Task.WaitAll(addBlackCars, addNonBlackCars);
WriteLine($"At present, the repository contains {cars.Count} car(s).");
void ProcessNonBlackCarModels()
{
Car car;
car = new("Hyundai Creta", "Pearl");
WriteLine($"Adding: {car} using task-{Task.CurrentId}");
cars.TryAdd(car);
Thread.Sleep(1000);

car = new("Maruti Suzuki Alto 800", "Red");
WriteLine($"Adding: {car} using task-{Task.CurrentId}");
cars.TryAdd(car);
Thread.Sleep(1000);

car = new("Toyota Fortuner Avant", "Bronze");
WriteLine($"Adding: {car} using task-{Task.CurrentId}");
cars.TryAdd(car);
Thread.Sleep(1000);

WriteLine($"Task-{Task.CurrentId} will try removing one item now.");
if (cars.Count > 0)
{
cars.TryTake(out Car removeCar);
WriteLine($"Tried removing: {removeCar} using task-{Task.CurrentId}");
}
}

void ProcessBlackCarModels()
{
Car car;
car = new("Toyota Fortuner Attitude", "Black");
WriteLine($"Adding: {car} using task-{Task.CurrentId}");
cars.TryAdd(car);
Thread.Sleep(1000);

car = new("Hyundai Creta Abyss", "Black");
WriteLine($"Adding: {car} using task-{Task.CurrentId}");
cars.TryAdd(car);

// Putting a relatively long sleep so that the other task can finish in between.
Thread.Sleep(5000);

WriteLine($"Task-{Task.CurrentId} will try removing three items now.");

for (int i = 0; i < 3; i++)
{
if (cars.Count > 0)
{
cars.TryTake(out Car removeCar);
WriteLine($"Tried removing: {removeCar} using task-{Task.CurrentId}");
}
}

}

// Using primary constructor
class Car(string model, string color)
{
private string _model = model;
private string _color = color;

public override string ToString()
{
return $"[{_model}, {_color}]";
}
}
Вот пример вывода:

Код: Выделить всё

Adding: [Toyota Fortuner Attitude, Black] using task-1
Adding: [Hyundai Creta, Pearl] using task-2
Adding: [Maruti Suzuki Alto 800, Red] using task-2
Adding: [Hyundai Creta Abyss, Black] using task-1
Adding: [Toyota Fortuner Avant, Bronze] using task-2
Task-2 will try removing one item now.
Tried removing: [Toyota Fortuner Avant, Bronze] using task-2
Task-1 will try removing three items now.
Tried removing: [Hyundai Creta Abyss, Black] using task-1
Tried removing: [Toyota Fortuner Attitude, Black] using task-1
Tried removing: [Hyundai Creta, Pearl] using task-1
At present, the repository contains 1 car(s).
Обратите внимание, что задаче 1 необходимо украсть третий элемент в этом выводе, и она делает это путем удаления элемента, который был добавлен задачей 2 в начале, т. е. он был добавлен последним.
Насколько я понимаю, задача-1 должна была удалить элемент задачей-2, которая была добавлена ​​последней, но не последней. Пожалуйста, помогите мне исправить это понимание.

Подробнее здесь: https://stackoverflow.com/questions/783 ... her-thread
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»