Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F#: Adding items to a dictionary on a timer

I am creating a program which loads an assembly file (.dll) and executes methods within the assembly file on an interval and then attempts to store the result in a dictionary. The full code for that is here (pastebin.com). My issue is that it seems that adding things to a dictionary on a timer is causing the dictionary to be unable to update. I was able to cut down the relevant code reproducing this problem to the following:

type SomeThing() as this =
    do
        let timer = new System.Timers.Timer()
        timer.Elapsed.Add(this.AddItem)
        timer.Interval <- 3000.0
        timer.Enabled <- true
        timer.Start()

    member this.MyDict = new System.Collections.Generic.Dictionary<string, string>()

    member this.AddItem _ =
        this.MyDict.Add("hello", "world")
        printfn "%A" this.MyDict

let mything = new SomeThing()

The result, if run in an interactive session or in something like LINQPad, is an output of:

seq []
seq []
 .
 .
 .

Clearly the dictionary is not changing. I also confirmed in the Visual Studio debugger that the dictionary was not changing. It is almost as if the MyDict.Add line is being skipped. I assume that this has something to do with my use of a type/do statement, since using a timer and a dictionary outside of a type seems to be no issue.

Can anyone point out what I've done wrong?

like image 976
Michael Trittin Avatar asked Jul 20 '16 16:07

Michael Trittin


1 Answers

The problem is here:

member this.MyDict = new System.Collections.Generic.Dictionary<string, string>()

This is a readonly property whose return expression is new System.Collections.Generic.Dictionary<string, string>(). I.e., every time the property is read from, a new, different dictionary is returned. Here's what it would look like in C# if that helps:

Dictionary<string, string> MyDict => new Dictionary<string, string>();

Here's what you're after, using automatically implemented properties:

member val MyDict = new System.Collections.Generic.Dictionary<string, string>() with get

Equivalent C#:

Dictionary<string, string> MyDict { get; } = new Dictionary<string, string>();
like image 192
ildjarn Avatar answered Oct 15 '22 04:10

ildjarn