执行顺序中的奇怪行为。线程,异步和等待包含

时间:2016-03-21 15:55:41

标签: c# c++ multithreading async-await

这段代码主要是图像处理,但我遇到的不是语法错误“我们认为它是线程化的东西”。我正在开发一个我没写过的应用程序。这些代码是几个.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 ans开始执行语句,然后突然控制跳回到4,抛出一个错误,一直回到开头并执行switch(),在屏幕上弹出错误。然后,控件在最后返回line 387并继续执行该功能。从技术上讲,它在前一个语句完成执行之前执行了switch()。然后,无论最终结果是什么,都没有用,因为我们的“失败”案例已经执行。

地球上是否有人知道为什么会这样?这个问题会在哪里产生?以及如何解决它?感谢

修改

一旦提示错误(来自switch())弹出:

,“输出”窗口会显示此信息
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

这发生在文件4行518的catch()

“线程”窗口显示Main Thread从文件1-&gt; 4一直有控件(黄色箭头)。但是,一旦文件4调用5-> 6,Main Thread将丢失控件,“黄色箭头”将执行到Worker Thread 6.现在,在执行6时,Main Thread将控件收回4,抛出异常并执行catch(),但随后丢失控件返回Worker Thread并继续执行6 ..这是正常的吗?我从未使用线程,但这不符合逻辑,我在执行函数返回然后转发并继续时从未见过“流中断”。我喜欢学习部分,但它对于一个菜鸟来说很困惑..

1 个答案:

答案 0 :(得分:0)

两个可能的原因。

  1. 您可能会同时运行两次代码。可能在同一时间在不同的线程上(如果是,应该很容易在调试器中看到,打开“线程”视图)。可能在同一个线程上(如果线程调用await,则实现可能会启动一些异步操作,线程被释放,并再次调用等待)。

  2. VS调试器并不总是可靠的。在调试多线程代码时,有时我会看到奇怪的地址,但事实并非如此。要进行验证,请在第87行添加日志记录语句,例如Debug.WriteLine,如果那是C#。