Использование TaskCompletionSource<T>, чтобы вызывающий объект мог асинхронно ожидать следующего элемента без блокировкиC#

Место общения программистов C#
Anonymous
Использование TaskCompletionSource<T>, чтобы вызывающий объект мог асинхронно ожидать следующего элемента без блокировки

Сообщение Anonymous »

У меня есть класс, который обрабатывает бесконечный поток данных. У меня также есть внешние компоненты, которые хотели бы время от времени асинхронно выполнять выборку обработанных данных. Поскольку до обработки «следующего элемента» может пройти некоторое время, я бы хотел, чтобы компоненты инспектора данных «ожидали» элемента, чтобы они не блокировались. Это может быть любое количество различных компонентов проверки данных, и если несколько инспекторов ожидают элемента, ничего страшного, если все они получат один и тот же экземпляр элемента.
У меня есть реализация ниже, использующая TaskCompletionSource , и кажется, что он работает нормально, но DataProcessor использует полный поток для обработки данных, а не задачу. Если бы я переключился на задачу, блокировка вызвала бы проблемы. Я также хотел бы по возможности избегать блокировки, потому что в подавляющем большинстве случаев ничего не пытается проверить элементы.

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

public class DataProcessor
{
private object _getDataLock = new object();
private TaskCompletionSource _getData;
private Thread _processThread;

public DataProcessor()
{
_processThread = new(ProcessDataLoop);
_processThread.Start();
}

void ProcessDataLoop()
{
while (true)
{
var processedData = ProcessNextData();

//This code in the lock is what I wonder about
lock (_getDataLock)
{
_getData?.SetResult(processedData.Clone());
_getData = null;
}
}
}

public Task GetData(TimeSpan timeout)
{
// This is the code I'm wondering how to write without a lock
lock (_getDataLock)
{
_getData ??= new TaskCompletionSource();
return _getData.Task.WithTimeout(timeout);
}
}
}

public class DataInspector
{
private DataProcessor _processor;

public async Task InspectData()
{
var data = await _processor.GetData(TimeSpan.FromSeconds(30));
// look at data
}
}

Мне интересно, есть ли способ сделать то же самое без блокировки.


Подробнее здесь: https://stackoverflow.com/questions/783 ... or-the-nex

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