Этот код в основном предназначен для обработки изображений, но я испытываю не синтаксическую ошибку «Мы думаем, что это многопоточность». Я работаю над приложением, которое я не написал. Эти коды представляют собой несколько файлов .cpp / c #. Он работал нормально, но внезапно начал вести себя странно.
Обычно пользователь делает снимок и на line 85
, перед switch()
, шаг управления в несколько функций, чтобы в конечном итоге в последнем файле (1-> 6). Когда этот последний файл (6) завершает выполнение, управление возвращается обратно (6-> 1), и мы получаем «case
«к первому файлу, чтобы затем ввести switch()
, выполнить и продолжить.
1:
private async void measureButton_Click(object sender, RoutedEventArgs e)
{
// ..
// some code above
var result = await ((CaptureViewModel)DataContext).ProcessMeasurement(); // line 85
switch (result) // line 87 <<< Here the switch executes before line 85 finishes executing
{
// some code and cases below
// ....
2:
public async Task<AnalyzeCode> ProcessMeasurement()
{
if (currentSession.Type == SessionType.Calibration)
return await TakeCalibrationImage();
return AnalyzeCode.NoSessionSelected;
}
3:
public async Task<AnalyzeCode> TakeCalibrationImage()
{
if (calibrationData.Count < maxCalibrationImages)
{
try
{
var data = await cameraController.TakeMeasurement(currentSession.Calibration, SessionType.Calibration);
// some code below
// ..
4:
public async Task<Measurement> TakeMeasurement(Calibration calibration, SessionType type)
{
try
{
switch (type)
{
case SessionType.Calibration:
// some code above
// ..
return await cameraClient.AnalyzeNextCalibrationAsync(); // line 518 Here it throws an exception error
// some code below
//..
5:
IObservable<Measurement>^ Client::AnalyzeNextCalibrationAsync()
{
return Observable::ObserveOn(
Observable::SubscribeOn(
Observable::Create<Measurement>(
gcnew Func<IObserver<Measurement>^, Action^>(
gcnew AnalyzeNextCalibrationSubscribeFactory(this),
&AnalyzeNextCalibrationSubscribeFactory::AnalyzeNext)),
Scheduler::TaskPool),
Scheduler::TaskPool);
}
class on_next_functor_3
{
public:
void operator ()(const tuple<frame, frame>& pair) const
{
Action<Measurement>^ on_next_delegate = this->on_next_delegate;
on_next_delegate(ConvertToCalibrationMeasurement(pair));
}
};
6:
Measurement ConvertToCalibrationMeasurement(const tuple<frame, frame>& pair)
{
// ...
// more code above
auto result1 = find_calibration_pattern(master_image); // line 386
auto result2 = find_calibration_pattern(slave_image); // line 387
// ..
// some code
// ..
return Measurement( // line 401
masterImage,
slaveImage,
ConvertToDateTime(master.time),
ConvertToTargets(result));
} // end of the function
Теперь вот недавнее странное поведение. Элемент управления вводит 6 и начинает выполнять оператор за оператором, затем внезапно элемент управления возвращается к 4, выдает ошибку и полностью возвращается к началу и выполняет switch()
который выскакивает ошибку на экране. Затем управление возвращается к line 387
в самом конце и продолжает выполнение этой функции. Так что технически он выполняет switch()
в 1, прежде чем предыдущий оператор завершает выполнение. Тогда каким бы ни был результат в самом конце, он не будет полезен, так как наш случай «сбой» уже выполнен.
Кто-нибудь на земле знает, почему это произошло? где бы возникла эта проблема? и как это исправить? Спасибо
Редактировать:
Окно «Вывод» показывает это, как только появляется сообщение об ошибке switch()
) pops:
Exception thrown: 'System.InvalidOperationException' in System.Reactive.Linq.dll
The thread 0x1574 has exited with code 0 (0x0).
Exception thrown: 'System.NullReferenceException' in App.exe
И это происходит в catch()
файла 4 строки 518
Окно потока показывает, что Main Thread
имеет элемент управления (желтая стрелка) полностью из файла 1-> 4. Однако, как только файл 4 вызывает 5-> 6, Main Thread
теряет контроль, и «желтая стрелка» переходит к Worker Thread
выполнение 6. Теперь, выполняя 6, Main Thread
возвращает управление в 4, генерирует исключение и выполняет catch()
но затем теряет контроль, чтобы вернуться к этому Worker Thread
и продолжить выполнение 6 .. Это нормально? Я никогда не работал с потоками, но это не логично, и я никогда не видел «обрыва потока» при выполнении функции возврата, а затем перемотки вперед и продолжения. Мне нравится учебная часть, но это смущает новичка ..
Две возможные причины.
Возможно, вы выполняете свой код два раза одновременно. Возможно, в разных потоках одновременно (если да, это должно быть легко увидеть в отладчике, откройте представление «Потоки»). Возможно, в том же потоке (возможно, если поток вызвал await, реализация запустила некоторую асинхронную операцию, поток освободился и снова вызвал await).
Отладчик VS не всегда надежен. При отладке многопоточного кода иногда я вижу странные адреса, но это просто неправда. Для проверки добавьте запись о регистрации в строку 87, например, Debug.WriteLine, если это C #.
Других решений пока нет …