1

I have to post a simplified version of the code because it's quite big otherwise.

I have two threads running the same code in parallel, we can call them A and B.

I have an object which can be summarized as this:

let dataProcessor (settings) =
    async {
        let orderEventHandler = Handler<OrderData>(fun _ orderData ->
                do some stuff with orderData
            )

        try
            externalEvent.AddHandler(orderEventHandler)

            // do a bunch of stuff in a loop

        finally
            externalEvent.RemoveHandler(orderEventHandler)
    }

and then I start multiple instances of this:

Async.StartAsTask(dataprocessor settings1)
Async.StartAsTask(dataprocessor settings2)

These tasks get routinely created and destroyed.

The issue I am facing is that the first task is getting all the events, but the second one doesn't seem to get them reliably. I have printed out logs and some events simply do not arrive.

I realize it is a simplified version of the code, so the issue may not be apparent. My question is: am I missing something obvious here?

Thomas
  • 10,933
  • 14
  • 65
  • 136
  • You are adding handler and removing it. externalEvent may not have a chance to raise an event during that time. Do you expect to handle events during "// do a bunch of stuff in a loop"? – Bartek Kobyłecki Jan 12 '21 at 09:17
  • @BartekKobyłecki, the loop part is long lived, it can last a few hours. I should have precised that. From what I am reading, it looks like F# events are not thread safe when it comes to adding / removing events. – Thomas Jan 12 '21 at 16:20
  • I don't know how a delegate list would be less thread-safe in F# than C#, but maybe F# is mutating the delegate list instead of appending to it? You could try decompiling to C# with SharpLab.io and see what's going on. – EricP Jan 12 '21 at 23:17
  • 1
    @EricP, I found this: https://stackoverflow.com/questions/35109354/using-a-f-event-and-asynchronous-in-multi-threaded-code that seems to have a similar problem. I haven't had a chance to try their solution yet – Thomas Jan 12 '21 at 23:18
  • @Thomas that's really interesting. So if it was a concurrency issue, then sometimes both dataProcessors work, and sometimes only one works? Does putting a Thread.Sleep between the Async.StartAsTasks change anything? – EricP Jan 13 '21 at 18:45
  • 1
    I haven't tried the Thread.Sleep, but I would imagine it would fix it because the ConcurrentEvent object (2nd answer from the question above) does fix the problem. – Thomas Jan 13 '21 at 18:47

0 Answers0