Когда вы делаете async
/ await
, вы в основном хотите, чтобы все (большинство) ваших методов работали в async
/ await
. На данный момент вы смешиваете асинхронные и не асинхронные вызовы методов. Это называется блокировкой в контексте async
, и его следует избегать , не в последнюю очередь из-за того, что это может привести к тупикам. Я бы посоветовал вам прочитать Async / Await - Best Practices в асинхронном программировании
В целом (и для некоторого упрощения проблемы) все ваши методы должны иметь подпись
public async Task method()
{
}
и всех , которые должны вызываться вашими методами:
await method();
private async void startDistanceMonitoring()
Никогда не используйте async void
(это только для асинхронных обработчиков событий)
private void Sleep(int NoOfMs)
{
Task.Delay(NoOfMs).Wait();
}
это блокировка, это должно быть
private async Task Sleep(int NoOfMs)
{
await Task.Delay(NoOfMs);
}
Когда вы звоните:
[ 115]
startDistanceMonitoring
- это метод async
, но вы его не ожидаете. Так что ваша программа может очень хорошо завершиться, прежде чем она будет завершена. Это должно быть:
await startDistanceMonitoring();
Вы делаете это неправильно во всем этом блоке кода. Всегда вызывайте методы async
с await
.
Ваш метод ввода не async
, public void Run(IBackgroundTaskInstance taskInstance)
должен быть public async Task Run(IBackgroundTaskInstance taskInstance)
Да, это ориентировано на многопотоковое исполнение.
Синхронизируемый блок должен предотвратить несколько потоков от ненужного вызова computeFieldValue()
. С тех пор field
энергозависимо, доступы в reset
и getField
все упорядочены.
Если первая проверка является непустой, getField
сделан; result
возвращается.
Иначе блокировка получена, исключая любой другой поток, который мог бы установить поле на непустой указатель, но разрешающий любой поток установить field
к пустому указателю. Если поток действительно устанавливает field
к пустому указателю ничто не должно было изменяться; это - условие, которое получило поток в синхронизируемый блок. Если другой поток уже получил блокировку после проверки текущего потока и установил поле на ненулевое значение, вторая проверка обнаружит это.
Я думаю, что это должно быть безопасно, но только потому, что Вы храните поле в локальной переменной. После того, как это сделано, нет никакого пути к локальной ссылке на переменной для волшебного изменения на пустой указатель, даже если другой поток сбрасывает значение поля на полпути через.
Кажется, что это будет работать, пока метод сброса reset()
метод упоминается выше. Однако, если reset()
метод инстанцирует нового Объекта (как ниже), разве Вы не могли закончить тем потенциально, что возвратили что-то другое, чем Вы предназначили?
void reset() {
field = new FieldType();
}
Я предполагаю, что это зависит от точно, под чем Вы подразумеваете ориентированный на многопотоковое исполнение.
Вы могли закончить с ситуацией, где первая инстанция используется после секунды. Это может быть хорошо, или это не может.