f#控制台应用程序完全轰炸忽略错误处理



请原谅所有的Console.WriteLines!试着弄清楚这里发生了什么。

如果我在visual studio中运行,下面的代码可以工作。当我编译并将其作为命令行程序运行时-尝试使用HttpClient访问API的行完全停止整个过程并结束程序。没有错误处理,什么都没有。这是怎么发生的?如果我也删除try/with块,它就会爆炸。我很困惑。

let getTransactionData(ewayCSVData: EwayCSVData, httpClient: HttpClient) = task{
try
Console.WriteLine("get transaction data 1")
if ewayCSVData.transactionType.ToLower() = "refund" then 
Console.WriteLine("get transaction data 2")
let url = "https://api.ewaypayments.com/Transaction/"+ewayCSVData.transactionNumber.ToString() + "/Refund"
Console.WriteLine("get transaction data 3")
let! postResult = httpClient.PostAsync(url, null)
Console.WriteLine("get transaction data 4")
let! result = postResult.Content.ReadAsStringAsync()
Console.WriteLine("get transaction data 5")
return result
else
Console.WriteLine("get transaction data 6")
let url: string = "https://api.ewaypayments.com/Transaction/"+ewayCSVData.transactionNumber
let! result = httpClient.GetStringAsync(url) // This line kills the whole process
Console.WriteLine("get transaction data 7")
return result
with (ex) -> 
Console.Write(ex.Message)
Console.WriteLine("get transaction data 8")
return ""
}

我怀疑您的命令行程序退出只是因为它已达到其代码的末尾。您正在启动一个异步任务来访问API,但是您的程序在退出之前没有等待该任务完成。这就是为什么没有异常或错误消息。

要解决这个问题,您可以显式地等待结果(例如通过Task.Result),或者在程序末尾放置一些东西以防止主线程退出。一种常见的方法是在顶级函数的最后一行调用Console.ReadLine()

例如,以下程序(通常)不向控制台写入任何内容而退出:

open System
open System.Threading.Tasks
Task.Run<unit>(fun () ->
Console.WriteLine("Hello world"))
|> ignore

你可以通过调用Result:

来修复这个问题
let task = Task.Run<unit>(fun () ->
Console.WriteLine("Hello world"))
task.Result

或调用Console.ReadLine:

Task.Run<unit>(fun () ->
Console.WriteLine("Hello world"))
|> ignore
Console.ReadLine() |> ignore

注意,我的例子使用Task.Run来说明这一点。我不认为f#task生成器的行为方式完全相同,但从你的描述中听起来足够相似。

最新更新