【问题标题】:System.FormatException error when multithreading多线程时 System.FormatException 错误
【发布时间】:2020-08-08 06:38:49
【问题描述】:

我需要为一个实现锁定以避免竞争条件的小 F# 项目创建两个线程。 (我已经扫描了 StackOverflow 的答案无济于事,因此这篇文章)

代码如下:

let bookFood _ =
    Console.WriteLine("Enter amount of grocery bags: ")
    let groceryBags = int(Console.ReadLine())
    Console.WriteLine("Enter customer name: ")
    let name = string(Console.ReadLine().ToString())
    let book bags name orders = 
        lock(bags,name) (fun()-> orders |> List.map (fun order ->
            if order.bags = bags then { order with customer = name }
            else order ))    
    orders <- book groceryBags name orders

ThreadPool.QueueUserWorkItem(WaitCallback(bookFood)) |> ignore
ThreadPool.QueueUserWorkItem(WaitCallback(bookFood)) |> ignore
Thread.Sleep(5000)

当我运行此代码时会发生以下问题:

系统提示我输入购物袋的数量两次(应该是这样吗?因为我调用了 bookFood 函数两次,对吧?)

然后我被提示输入客户名称,一旦我输入这个应用程序崩溃并出现以下错误: System.FormatException has been throwed, the input string is not the correct format.

我到处寻找解决方案,但我现在正在寻求帮助。

澄清:

我该如何解决这个问题?是因为我错误地编码了锁定还是我没有正确创建两个线程?当我只调用一次 bookFood 方法时,它工作得很好,但是该任务需要我创建两个线程并使用锁定来避免竞争条件,这就是我得到这个错误的时候。

非常感谢这里活跃的 F# 社区提供帮助,您知道自己是谁。

【问题讨论】:

    标签: multithreading functional-programming f# locking f#-interactive


    【解决方案1】:

    如果您使用的是调试器,您应该会发现它的中断点是:

    let groceryBags = int(Console.ReadLine())
    

    请记住您是如何“提示输入购物袋数量两次”的——那是因为您在两个线程上运行对 ReadLine() 的调用。

    当你输入包数时,下一个ReadLine调用将是另一个book方法的“包数”,你在那里输入一个名字,不能转换成int,所以它会抛出一个异常,说它的格式不正确。

    如果您只输入了数字(包括名称),则不会出现此错误。

    1. Console 函数不是线程安全的,你真的不应该那样使用它。
    2. 使用Int32.TryParse 查看您的字符串是否与格式匹配,而不是在不匹配时抛出异常。
    3. 锁需要所有线程之间的共享对象。您正在每个锁中创建一个新的元组对象 - 这不会做任何事情。尝试锁定一个专门创建的锁对象,let gate = new Object() 就可以了。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-21
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多