Можно ли проверить, запущен ли метод с захваченным SynchronizationContext при запуске Задачей?

Что-то вроде следующего должно начать:

<?php

function sortDate($a, $b) {
    return strtotime($a['date']) - strtotime($b['date']);
}

$input = array('info' => array(array('id' => 2, 'date' => '2019-04-11'), array('id' => 1, 'date' => '2010-05-15')));

usort($input['info'], 'sortDate');
print_r($input);
0
задан Zer0 27 February 2019 в 17:00
поделиться

2 ответа

Создайте SynchronizationContext, который выдает исключение в реализации Post и Send. В качестве альтернативы, он может установить логическое значение, указывающее, были ли вызваны Send или Post, что позволит вам проверить это логическое значение позже (если вы сделаете это, вы, вероятно, захотите запустить предоставленный делегат, иначе вы могли бы рискнуть тупиковую ситуацию).

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

0
ответ дан Servy 27 February 2019 в 17:00
поделиться

Цель состоит в том, чтобы отсеять неправильное использование ConfigureAwait в очень большой кодовой базе.

Некоторые команды выбирают для этого инструмент анализа кода. Есть несколько доступных. Наиболее распространенный подход, который я видел, состоит в том, чтобы потребовать a ConfigureAwait для каждого await и явно указать либо true, либо false. Это гарантирует, что каждый await был рассмотрен и поток контекста явно. Другие команды применяют специфичные для проекта правила «всегда использовать ConfigureAwait(false)» и просто зависят от проверки кода для проектов, которые не могут следовать этому правилу.

Проблема с вашим примером кода состоит в том, что невозможно для DoWhatever узнать, был ли он вызван косвенно, из-за Task.Run. Если вы переписываете эти методы, это становится ясным:

public static async Task CapturesContext()
{
  var task = Task.Run(() => DoWhatever());
  await task;
}

public static async Task DoesNotCaptureContext()
{
  var task = Task.Run(() => DoWhatever());
  var configuredTask = task.ConfigureAwait(false);
  await configuredTask;
}

Первые строки переписанных методов должны прояснить, что DoWhatever не имеет представления, захватят ли CapturesContext или DoesNotCaptureContext контекст или не. Обратите внимание на «волю» (будущее время) - вполне возможно, что DoWhatever выполняется и заканчивает выполнение до того, как ConfigureAwait(false) даже будет вызван.

Теперь вы можете проверить изнутри задачи, выполняется ли она в контексте прямо сейчас . Но в этом случае для обоих примеров методов DoWhatever не увидят контекст из-за Task.Run. Так что это не поможет вам обнаружить тот факт, что CapturesContext действительно захватывает контекст; DoWhatever не видит контекст, поэтому не может его обнаружить.

Пользовательский SynchronizationContext является хорошим решением для модульных тестов, но его было бы неудобно использовать во время выполнения, так как у вас есть некоторые методы, которым нужен контекст. По этой причине большинство команд предпочитают полагаться на проверку кода и / или инструменты анализа кода.

0
ответ дан Stephen Cleary 27 February 2019 в 17:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: