... Итак, если быть точным, вызов Take отображает элемент, добавленный
последним образом в этом потоке; если в этом потоке нет элементов, он
дает вам элемент, добавленный последним в другом потоке, выбранный
случайно.
На самом деле, в VS, если вы в глубине души, вы увидите этот комментарий к методу TrySteal(
Код: Выделить всё
TryTakeЕсли для этого потока нет локальной очереди, просто начните с головной
очереди и попробуйте воровать из каждой очереди, пока не получим результат. Если из этого потока
есть локальная очередь, то начните со следующей очереди
после нее, а затем выполните итерацию от головы до этой очереди,
не включая ее.
Теперь позвольте мне показать вам следующую программу:
Код: Выделить всё
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, которая была добавлена последней, но не последней. Пожалуйста, помогите мне исправить это понимание.
Подробнее здесь: https://stackoverflow.com/questions/783 ... her-thread
Мобильная версия