首页 \ 问答 \ 意外的行为与异步处理异步,可能的错误?(Unexpected behavior with exception handling in async, possible bug?)

意外的行为与异步处理异步,可能的错误?(Unexpected behavior with exception handling in async, possible bug?)

当调用嵌套异步时,我偶然发现了一个问题,而这恰好是空的。 引发了一个异常,但无法使用Async工作流提供的任何常规异常处理方法。

以下是重现问题的简单测试:

[<Test>]
let ``Nested async is null with try-with``() = 

    let g(): Async<unit> = Unchecked.defaultof<Async<unit>>

    let f = async {
            try
                do! g()
            with e ->  
                printf "%A" e
    }

    f |> Async.RunSynchronously |> ignore

这导致了以下例外:

System.NullReferenceException : Object reference not set to an instance of an object.
at Microsoft.FSharp.Control.AsyncBuilderImpl.bindA@714.Invoke(AsyncParams`1 args)
at <StartupCode$FSharp-Core>.$Control.loop@413-40(Trampoline this, FSharpFunc`2 action)
at Microsoft.FSharp.Control.Trampoline.ExecuteAction(FSharpFunc`2 firstAction)
at Microsoft.FSharp.Control.TrampolineHolder.Protect(FSharpFunc`2 firstAction)
at Microsoft.FSharp.Control.AsyncBuilderImpl.startAsync(CancellationToken cancellationToken,     FSharpFunc`2 cont, FSharpFunc`2 econt, FSharpFunc`2 ccont, FSharpAsync`1 p)
at Microsoft.FSharp.Control.CancellationTokenOps.starter@1121-1.Invoke(CancellationToken     cancellationToken, FSharpFunc`2 cont, FSharpFunc`2 econt, FSharpFunc`2 ccont, FSharpAsync`1 p)
at Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously(CancellationToken token, FSharpAsync`1 computation, FSharpOption`1 timeout)
at Microsoft.FSharp.Control.FSharpAsync.RunSynchronously(FSharpAsync`1 computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken)
at Prioinfo.Urkund.DocCheck3.Core2.Tests.AsyncTests.Nested async is null with try-with() in SystemTests.fs: line 345 

我真的认为应该在这种情况下发现异常,或者这确实是预期的行为? (我正在使用Visual Studio 2010 Sp1进行记录)

此外, Async.CatchAsync.StartWithContinuations展现了与这些测试用例所展示的相同的问题:

[<Test>]
let ``Nested async is null with Async.Catch``() = 

    let g(): Async<unit> = Unchecked.defaultof<Async<unit>>

    let f = async {
                do! g()
            }

    f |> Async.Catch |> Async.RunSynchronously |> ignore


[<Test>]
let ``Nested async is null with StartWithContinuations``() = 

    let g(): Async<unit> = Unchecked.defaultof<Async<unit>>

    let f = async {
                do! g()
            }

    Async.StartWithContinuations(f
                                , fun _ -> ()
                                , fun e -> printfn "%A" e
                                , fun _ -> ())

似乎在工作流生成器的绑定方法中引发了异常,我的猜测是正常的错误处理代码被绕过。 它看起来像是在执行异步工作流程时遇到的一个错误,因为我没有在文档或其他地方发现任何暗示这是预期行为的东西。

在大多数情况下,我认为这很容易解决,至少对我来说这不是一个大问题,但这有点令人不安,因为这意味着您无法完全信任异步异常处理机制以捕获所有异常。

编辑:

给它一些想法后,我同意kvb。 空的asyncs不应该真正存在于普通代码中,只有当你做了你可能不应该做的事情时(例如使用Unchecked.defaultOf)或使用反射来产生值(在我的情况下,它是一个模拟的框架) 。 因此它不是一个真正的bug,而更像是一个边缘案例。


I have stumbled upon a problem when calling a nested Async which happens to be null. An exception is raised but it can't be catched with any of the normal exception handling methods Async workflows provide.

The following is a simple test which reproduces the problem:

[<Test>]
let ``Nested async is null with try-with``() = 

    let g(): Async<unit> = Unchecked.defaultof<Async<unit>>

    let f = async {
            try
                do! g()
            with e ->  
                printf "%A" e
    }

    f |> Async.RunSynchronously |> ignore

which results in the follwing exception:

System.NullReferenceException : Object reference not set to an instance of an object.
at Microsoft.FSharp.Control.AsyncBuilderImpl.bindA@714.Invoke(AsyncParams`1 args)
at <StartupCode$FSharp-Core>.$Control.loop@413-40(Trampoline this, FSharpFunc`2 action)
at Microsoft.FSharp.Control.Trampoline.ExecuteAction(FSharpFunc`2 firstAction)
at Microsoft.FSharp.Control.TrampolineHolder.Protect(FSharpFunc`2 firstAction)
at Microsoft.FSharp.Control.AsyncBuilderImpl.startAsync(CancellationToken cancellationToken,     FSharpFunc`2 cont, FSharpFunc`2 econt, FSharpFunc`2 ccont, FSharpAsync`1 p)
at Microsoft.FSharp.Control.CancellationTokenOps.starter@1121-1.Invoke(CancellationToken     cancellationToken, FSharpFunc`2 cont, FSharpFunc`2 econt, FSharpFunc`2 ccont, FSharpAsync`1 p)
at Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously(CancellationToken token, FSharpAsync`1 computation, FSharpOption`1 timeout)
at Microsoft.FSharp.Control.FSharpAsync.RunSynchronously(FSharpAsync`1 computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken)
at Prioinfo.Urkund.DocCheck3.Core2.Tests.AsyncTests.Nested async is null with try-with() in SystemTests.fs: line 345 

I really think the exception should be caught in this case, or is this really the expected behavior? (I'm using Visual Studio 2010 Sp1 for the record)

Also, Async.Catch and Async.StartWithContinuations exhibits the same problem as demonstrated by these test cases:

[<Test>]
let ``Nested async is null with Async.Catch``() = 

    let g(): Async<unit> = Unchecked.defaultof<Async<unit>>

    let f = async {
                do! g()
            }

    f |> Async.Catch |> Async.RunSynchronously |> ignore


[<Test>]
let ``Nested async is null with StartWithContinuations``() = 

    let g(): Async<unit> = Unchecked.defaultof<Async<unit>>

    let f = async {
                do! g()
            }

    Async.StartWithContinuations(f
                                , fun _ -> ()
                                , fun e -> printfn "%A" e
                                , fun _ -> ())

It seems the exception is raised within the bind-method in the workflow builder and my guess is that as a result the normal error handling code is bypassed. It looks like a bug in the implementation of async workflows to me since I haven't found anything in the documentation or elsewhere which suggest that this is the intended behavior.

It is pretty easy to work around in most cases I think so it's not a huge problem for me at least but it is a bit unsettling since it means that you can't completely trust the async exception handling mechanism to be able to capture all exceptions.

Edit:

After giving it some thought I agree with kvb. Null asyncs should not really exist in normal code and could really only be produced if you do something you probably shouldn't (such as using Unchecked.defaultOf) or use reflection to produce the values (in my case it was a mocking framework involved). Thus it's not really a bug but more of an edge case.


原文:https://stackoverflow.com/questions/8923615
更新时间:2023-12-28 11:12

最满意答案

我解决了这个问题。 我正在给那些可能像我一样得到同样问题的人。 实际上问题不在于列出目录中的文件。 它工作正常。 但是当我拍摄照片时, listfiles会在图片字节写入sdcard文件夹之前获取文件列表。 所以我通过在文件写入文件夹之后获取​​文件来改变编码。 我只是调用像CameraTestActivity.LoadImagefromSD();这样的文件加载方法CameraTestActivity.LoadImagefromSD(); 以下是编码。

/// Handles data for jpeg picture
    private PictureCallback jpegCallback = new PictureCallback()
    {
      @Override
      public void onPictureTaken(byte[] data, Camera camera) 
      {
        //immediately start the preview again
        ///@see http://developer.android.com/reference/android/hardware/Camera.html#takePicture%28android.hardware.Camera.ShutterCallback,%20android.hardware.Camera.PictureCallback,%20android.hardware.Camera.PictureCallback,%20android.hardware.Camera.PictureCallback%29
        if (mCamera != null)
          mCamera.startPreview();

        FileOutputStream outStream = null;
        try {
          // Write to SD Card
              outStream = new FileOutputStream(String.format(Environment.getExternalStorageDirectory().getAbsolutePath()+"/images/%d.jpg",
            System.currentTimeMillis()) );
              // outStream = new FileOutputStream(String.format("/data/data/com.mattikariluoma.cameratest/files/images/%d.jpg",
          outStream.write(data);
          outStream.close();
          Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
          CameraTestActivity.LoadImagefromSD();

        } catch (FileNotFoundException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        } finally {
        }

        Log.d(TAG, "onPictureTaken - jpeg");
      }
    };

希望它会帮助某人。


I solved the problem. I am giving the answer for fellows who might get the same problem as like me. Actually the problem is not in listing files from directory. It is working correctly. But when i take the picture, the listfiles get the files list before the picture bytes write to the sdcard folder. So i changed the coding by getting the files only after the bytes write to the folder. I just call the files loading method like this CameraTestActivity.LoadImagefromSD(); Following is the coding for it.

/// Handles data for jpeg picture
    private PictureCallback jpegCallback = new PictureCallback()
    {
      @Override
      public void onPictureTaken(byte[] data, Camera camera) 
      {
        //immediately start the preview again
        ///@see http://developer.android.com/reference/android/hardware/Camera.html#takePicture%28android.hardware.Camera.ShutterCallback,%20android.hardware.Camera.PictureCallback,%20android.hardware.Camera.PictureCallback,%20android.hardware.Camera.PictureCallback%29
        if (mCamera != null)
          mCamera.startPreview();

        FileOutputStream outStream = null;
        try {
          // Write to SD Card
              outStream = new FileOutputStream(String.format(Environment.getExternalStorageDirectory().getAbsolutePath()+"/images/%d.jpg",
            System.currentTimeMillis()) );
              // outStream = new FileOutputStream(String.format("/data/data/com.mattikariluoma.cameratest/files/images/%d.jpg",
          outStream.write(data);
          outStream.close();
          Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
          CameraTestActivity.LoadImagefromSD();

        } catch (FileNotFoundException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        } finally {
        }

        Log.d(TAG, "onPictureTaken - jpeg");
      }
    };

Hope it will help someone.

相关问答

更多

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。