我无法解决为什么以下代码无法捕获异常。这是我第一次使用F#中的Async,所以我确定它很简单
open System
open Microsoft.WindowsAzure
open Microsoft.WindowsAzure.StorageClient
open System.Windows.Forms
let mutable connection = "UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://ipv4.fiddler"
CloudStorageAccount.SetConfigurationSettingPublisher(fun cName cPublisher ->
cPublisher.Invoke connection |> ignore)
let storageAccount = CloudStorageAccount.Parse connection
let createTable tableName =
let client = storageAccount.CreateCloudTableClient()
async{
try
do! Async.FromBeginEnd(tableName, client.BeginCreateTable , client.EndCreateTable)
MessageBox.Show "Created" |>ignore
with
| :? StorageClientException -> printfn "failed"; MessageBox.Show("failed to create table") |> ignore
| _ -> printfn "Failed with unknown exception"
} |> Async.Start
[<EntryPoint; STAThread>]
let main(args) =
let form = new Form()
let btn = new Button(Text = "Click")
btn.Click.AddHandler(fun _ _ -> createTable "SomeNewTable")
form.Controls.Add btn
let result = form.ShowDialog()
0
如果我运行它并且已经创建了表,则表示代码中没有处理类型为StorageClientException的异常,特别是指向FromBeginEnd调用的client.EndCreateTable部分
答案 0 :(得分:4)
这有点像在VS2010 SP1中的FSharp.Core中修复的问题。 .NET SynchronizationContext
改变了它们的行为(我认为在.NET 4.0 SP1中),我们需要对异步的F#运行时进行相应的更改才能正确处理线程关联。
我认为你可以在这里抓住更新的FSharp.Core:http://www.microsoft.com/download/en/details.aspx?DisplayLang=en&id=15834
答案 1 :(得分:2)
如果异常的原因是该表已经存在,为什么不使用 BeginCreateTableIfNotExist
/ EndCreateTableIfNotExist
。
<强>更新强>
该错误与Windows Azure无关。我可以用一个简单的程序重现相同的行为:
open System
open System.Windows.Forms
let bufferData = Array.zeroCreate<byte> 100000000
let async1 filename =
async{
try
use outputFile = System.IO.File.Create(filename)
do! outputFile.AsyncWrite(bufferData)
MessageBox.Show("OK") |> ignore
with
| :? ArgumentException -> printfn "Failed with ArgumentException"; MessageBox.Show("Failed with ArgumentException") |> ignore
| _ -> printfn "Failed with unknown exception"; MessageBox.Show("Failed with unknown exception") |> ignore
} |> Async.Start
let main(args) =
let form = new Form(Text = "Test Form")
let button1 = new Button(Text = "Start")
let button2 = new Button(Text = "Start Invalid", Top = button1.Height + 10)
form.Controls.AddRange [| button1; button2; |]
button1.Click.Add(fun args -> async1 "longoutput.dat")
// Try an invalid filename to test the error case.
button2.Click.Add(fun args -> async1 "|invalid.dat")
let result = form.ShowDialog()
0
let _ = main([||])
奇怪的是代码在F#Interactive中正常工作,但在Visual Studio中调试为Windows应用程序时无法捕获异常(无论是调试还是发布配置)。即使是陌生人,如果在Visual Studio之外作为应用程序执行,它也能正常工作。
如果你想知道,这个程序改编自a MSDN example,它表现出相同的问题。
更新2:
http://cs.hubfs.net/topic/Some/0/59516已经提出了类似的问题。正如@ildjarn和@Brian所指出的,VS2010 SP1中修复了这个bug。如果没有VS2010 SP1,您可以使用F#Interactive测试代码并在VS外部执行应用程序而不会出现任何问题。
答案 2 :(得分:2)
感谢Don Syme, 解决方案是关闭调试“只是我的代码”。 调试 - &gt;选项和设置 - &gt;一般 - &gt;取消选中“仅启用我的代码(仅管理)
”这仍然是Windows 8消费者预览版中出现的Visual Studio 11测试版的问题。