Я использую собственную библиотеку через вызовы PInvoke, которая возвращает байт * и хочу убедиться, что в сценарии производитель / потребитель поток потока получает последние данные.
У меня есть очень надуманный пример, чтобы попытаться проиллюстрировать то, что я спрашиваю.Я знаю о «горячей петле» в Consumer
(это всего лишь пример, реальный код намного больше и его невозможно вставить сюда).
public unsafe class ThreadExample {
class PInvokeResult {
public Byte* Data;
public Int32 Length;
}
// Shared Objects Used For Synchronization
Object SyncRoot = new Object();
Queue<PInvokeResult> WorkQueue = new Queue<PInvokeResult>();
// Producer Thread
void Producer() {
while (true) {
PInvokeResult workItem;
workItem = new PInvokeResult();
workItem.Data = PInvokeNativeLongRunningCall(out workItem.Length);
lock (SyncRoot) {
WorkQueue.Enqueue(workItem);
}
}
}
// Consume Thread
void Consumer() {
while (true) {
bool workAvailable = false;
PInvokeResult workItem = null;
lock (SyncRoot) {
if (WorkQueue.Count > 0) {
workItem = WorkQueue.Dequeue();
workAvailable = true;
}
}
if (workAvailable) {
ProcessWorkItem(workItem);
PInvokeReturnPointerBuffer(workItem.Data);
}
}
}
}
Блокировка здесьдостаточно, чтобы убедиться, что данные, считываемые с указателя Byte*
на PInvokeResult, никогда не указывают на «устаревшие» данные для потребителя?
В данном случае я имею в виду устаревшие данные:
- Один конкретный буфер байта * возвращается из вызова
PInvokeNativeLongRunningCall
. - Буфер передаетсяот производителя до потребителя это использует блокировку SyncRoot, чтобы убедиться, что доступ к очереди безопасен.
- Потребитель выполняет некоторую работу над элементом и затем возвращает его в собственный код через
PInvokeReturnPointerBuffer
- Затем буфер перерабатывается и используется повторно на собственной стороне, а данные в буфере сначала устанавливаются на все нули, а затем записываются снова.
- Затем цикл начинается с
1.
Когда буфер второй раз приходит к потребителю, как я могу быть уверен, что данные, которые он видит, являются последними новыми данными, записанными вызовом PInvoke?
Этот вопрос чисто с точки зрения C #, я знаю, что нативный код - хороший и надежный, это хорошо используемая библиотека.
Это даже то, что язык должен учитывать, или этоКолорадополностью обрабатывается самим процессором?