F#程序在fsi中正确运行,但作为exe挂起

时间:2016-12-30 00:23:01

标签: f# f#-interactive

我有一段代码在MailboxProcessor收到消息时向数据库添加一行。它在fsi中运行时可以正常工作,但在编译为exe时会挂起。脚本如下:

#r "../packages/Newtonsoft.Json/lib/net40/Newtonsoft.Json.dll"
#r "../packages/SQLProvider/lib/FSharp.Data.SqlProvider.dll"

open Newtonsoft.Json
open FSharp.Data.Sql
open System

let [<Literal>] ResolutionPath = __SOURCE_DIRECTORY__ + "/../build/" 
let [<Literal>] ConnectionString = "Data Source=" + __SOURCE_DIRECTORY__ + @"/test.db;Version=3"

// test.db is initialized as follows:
//
// BEGIN TRANSACTION;
//    CREATE TABLE "Events" (
//        `id`INTEGER PRIMARY KEY AUTOINCREMENT,
//        `timestamp` DATETIME NOT NULL
//    );
//    COMMIT;

type Sql = SqlDataProvider< 
            ConnectionString = ConnectionString,
            DatabaseVendor = Common.DatabaseProviderTypes.SQLITE,
            ResolutionPath = ResolutionPath,
            IndividualsAmount = 1000,
            UseOptionTypes = true >
let ctx = Sql.GetDataContext()

let agent = MailboxProcessor.Start(fun (inbox:MailboxProcessor<String>) ->  
    let rec loop() =
        async {
            let! msg = inbox.Receive()
            match msg with
            | _ ->
              let row = ctx.Main.Events.Create()
              row.Timestamp <- DateTime.Now
              printfn "Submitting"
              ctx.SubmitUpdates()
              printfn "Submitted"
            return! loop() 
        }
    loop() 
)

agent.Post "Hello"

编译为exe时,会打印“正在提交”,但随后会挂起。如果你想尝试一下,完整的代码就在github here

1 个答案:

答案 0 :(得分:5)

似乎问题是主要线程在MailboxProcessor处理它的邮箱之前退出。 FSI是长寿的,所以这并没有发生。我改变了:

[<EntryPoint>]
let main argv =
    agent.Post "Hello"
    agent.Post "Hello again"
    0

[<EntryPoint>]
let main argv =
    agent.Post "Hello"
    agent.Post "Hello again"
    let waitLoop = async {
        while agent.CurrentQueueLength > 0 do
            printfn "Sleeping"
            do! Async.Sleep 1000
        }
    Async.RunSynchronously waitLoop
    0

现在代码按照我的意图执行。