意外的行为与异步处理异步,可能的错误?(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.Catch
和Async.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
andAsync.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
最满意答案
我解决了这个问题。 我正在给那些可能像我一样得到同样问题的人。 实际上问题不在于列出目录中的文件。 它工作正常。 但是当我拍摄照片时,
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 thisCameraTestActivity.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.
相关问答
更多-
如果我理解正确,问题是当你给gulp.src一个数组时,gulp不知道“base”文件夹在哪里。 尝试执行以下操作: gulp.src(["src/*.html", "src/templates/**/*"], { base: 'src' }).pipe(gulp.dest("build/")); 这样,gulp知道哪个文件夹是你的基本文件夹,并将首先从'src'复制文件夹结构。 之后,gulp会将文件复制到正确的位置。 If I understand corre ...
-
您可以将DateCreated与FileSystemObject一起使用。 对当前代码进行一些小调整即可 我也提到了这些变量 Sub CheckFileTimes() Dim StrFile As String Dim StrCDate As Date Dim fso As Object Dim f As Object 'set up output file Set fso = CreateObject("Scripting.FileSystemObject") Set f = fso.Ope ...
-
ListFiles第一次没有正确获取文件夹文件(ListFiles is not getting the folder files correct on first time)[2023-04-22]
我解决了这个问题。 我正在给那些可能像我一样得到同样问题的人。 实际上问题不在于列出目录中的文件。 它工作正常。 但是当我拍摄照片时, listfiles会在图片字节写入sdcard文件夹之前获取文件列表。 所以我通过在文件写入文件夹之后获取文件来改变编码。 我只是调用像CameraTestActivity.LoadImagefromSD();这样的文件加载方法CameraTestActivity.LoadImagefromSD(); 以下是编码。 /// Handles data for jpeg pic ... -
Windows批处理脚本,一次压缩文件夹中的文件500个文件(Windows batch script to zip files in a folder 500 files at a time)[2022-10-21]
你的问题似乎在这里: for %f in (*) do ( echo [!i!] & set /a i+=1 echo %f >> %listfile% if !i!==%n% ( 7z a %output%\!z!.zip @%listfile% set i=0 set /a z+=1 del %listfile% ) ) 批处理文件中的for循环要求将元metavariable (在本例中为f )指定为% ... -
为什么Delphi不在正确的文件夹中输出DCU文件?(Why Delphi does not output the DCU files in the correct folder?)[2022-05-16]
从文档 : 输出目录 指定编译器应该放置可执行文件的位置。 单位输出目录 指定一个单独的目录来包含已编译的单位(.dcu)。 这听起来像你需要指定单位输出目录以及输出目录。 我个人倾向于将这两个目录分开。 From the documentation: Output directory Specifies where the compiler should put the executable file. Unit output directory Specifies a separate director ... -
是否有一个“正确”的文件夹,用于在dart中放置测试资源?(Is there a “correct” folder where to place test resources in dart?)[2022-06-25]
我检查System.currentDirectory是否是包含pubspec.yaml文件的目录,如果不是,我向上移动当前目录,直到找到包含pubpsec.yaml文件的目录,然后继续测试代码。 I check if System.currentDirectory is the directory containing the pubspec.yaml file, if not I move the current directory upwards until I found the directory ... -
启用扩展(默认)后, mkdir将在一个步骤中创建中间文件夹。 所以你要做的就是 迭代文件 使用子串将文件名拆分为部分和 如果尚未存在,则创建文件夹。 @echo off & setlocal EnableDelayedExpansion set Src=A:\ set Dst=A:\ for /f "delims=" %%A in ('Dir /B "%Src%*.pdf"') do ( Set "File=%%A" set "Folder=%Dst%\!File:~0,2!\!File: ...
-
只能从main()读取文件夹/目录?(can only read folder/directory from main() ? listfiles() returns null?)[2023-08-08]
下面的代码工作正常,只要路径是正确的。 我假设你的路径必须是无效的。 由于File :: listFiles将返回空,如果目录不存在。 private Listget_files_paths(String data_path) { File folder = new File(data_path); if(!folder.exists() || !folder.isDirectory()){ throw new IllegalArgumentExceptio ... -
在升级过程中,Windows Installer使用文件版本控制规则来确定是否安装了文件。 要在升级期间安装所有文件,您可以确保: 所有文件都放在具有版本化文件作为关键成员的组件中 与旧安装相比,所有关键成员文件的文件版本都更高 Windows Installer根据其关键成员评估是否安装组件。 因此,如果密钥成员文件的版本高于计算机上的版本,则安装该组件。 另一种解决方案是将File表中的Version列设置为较高的值,例如65535.65535.65535.65535。 这样,Windows Insta ...
-
Gradle复制任务不是第一次从临时文件夹复制文件(Gradle copy task not copying files from temp folder first time around)[2022-07-21]
复制任务很棘手。 只有在配置阶段找到要复制的内容时,才会执行复制任务。 如果在该阶段没有找到任何东西,它将被跳过。 您可以使用复制方法而不是复制任务。 prepare( dependsOn: 'copyRequiredJarFilesToWebContent' ) {} task unpackWar( type: Copy ) { def warFile = file( warFileLocation ) from zipTree( warFile ) into 'Temp' ...