From 4956021086999670674f6632bb37d8db4022182e Mon Sep 17 00:00:00 2001 From: Dmitry Dembinsky <2384012+xloggr@users.noreply.github.com> Date: Sun, 11 Apr 2021 23:26:08 -0400 Subject: [PATCH 1/2] add StartImmediate method to the MailboxProcessor (#11370) --- src/fsharp/FSharp.Core/mailbox.fs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/mailbox.fs b/src/fsharp/FSharp.Core/mailbox.fs index 96782fa1e15..899e71255a2 100644 --- a/src/fsharp/FSharp.Core/mailbox.fs +++ b/src/fsharp/FSharp.Core/mailbox.fs @@ -325,6 +325,11 @@ namespace Microsoft.FSharp.Control type AsyncReplyChannel<'Reply>(replyf : 'Reply -> unit) = member x.Reply value = replyf value + module private AsyncStarter = + type Func = Async -> CancellationToken -> unit + let asyncStart c ct = Async.Start(computation=c, cancellationToken=ct) + let asyncStartImmediate c ct = Async.StartImmediate(computation=c, cancellationToken=ct) + [] [] [] @@ -350,7 +355,7 @@ namespace Microsoft.FSharp.Control member _.UnsafeMessageQueueContents = mailbox.UnsafeContents #endif - member x.Start() = + member private x.StartWith(startAsync: AsyncStarter.Func) = if started then raise (new InvalidOperationException(SR.GetString(SR.mailboxProcessorAlreadyStarted))) else @@ -365,7 +370,13 @@ namespace Microsoft.FSharp.Control with exn -> errorEvent.Trigger exn } - Async.Start(computation=p, cancellationToken=cancellationToken) + startAsync p cancellationToken + + member x.Start() = + x.StartWith(AsyncStarter.asyncStart) + + member x.StartImmediate() = + x.StartWith(AsyncStarter.asyncStartImmediate) member _.Post message = mailbox.Post message @@ -438,3 +449,8 @@ namespace Microsoft.FSharp.Control let mailboxProcessor = new MailboxProcessor<'Msg>(body, ?cancellationToken=cancellationToken) mailboxProcessor.Start() mailboxProcessor + + static member StartImmediate(body, ?cancellationToken) = + let mailboxProcessor = new MailboxProcessor<'Msg>(body, ?cancellationToken=cancellationToken) + mailboxProcessor.StartImmediate() + mailboxProcessor From 5ff26eda88a8e70a1cee3f420912042f511a9904 Mon Sep 17 00:00:00 2001 From: Dmitry Dembinsky <2384012+xloggr@users.noreply.github.com> Date: Fri, 7 May 2021 07:41:06 -0400 Subject: [PATCH 2/2] address review comments: - remove AsyncStarter module - add unit test --- src/fsharp/FSharp.Core/mailbox.fs | 24 +++++++++-------------- tests/fsharp/core/controlMailbox/test.fsx | 8 ++++++++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/mailbox.fs b/src/fsharp/FSharp.Core/mailbox.fs index 899e71255a2..20b426cd0eb 100644 --- a/src/fsharp/FSharp.Core/mailbox.fs +++ b/src/fsharp/FSharp.Core/mailbox.fs @@ -325,11 +325,6 @@ namespace Microsoft.FSharp.Control type AsyncReplyChannel<'Reply>(replyf : 'Reply -> unit) = member x.Reply value = replyf value - module private AsyncStarter = - type Func = Async -> CancellationToken -> unit - let asyncStart c ct = Async.Start(computation=c, cancellationToken=ct) - let asyncStartImmediate c ct = Async.StartImmediate(computation=c, cancellationToken=ct) - [] [] [] @@ -355,7 +350,7 @@ namespace Microsoft.FSharp.Control member _.UnsafeMessageQueueContents = mailbox.UnsafeContents #endif - member private x.StartWith(startAsync: AsyncStarter.Func) = + member private x.PrepareStart() = if started then raise (new InvalidOperationException(SR.GetString(SR.mailboxProcessorAlreadyStarted))) else @@ -364,19 +359,18 @@ namespace Microsoft.FSharp.Control // Protect the execution and send errors to the event. // Note that exception stack traces are lost in this design - in an extended design // the event could propagate an ExceptionDispatchInfo instead of an Exception. - let p = - async { try - do! body x - with exn -> - errorEvent.Trigger exn } - - startAsync p cancellationToken + async { try + do! body x + with exn -> + errorEvent.Trigger exn } member x.Start() = - x.StartWith(AsyncStarter.asyncStart) + let p = x.PrepareStart() + Async.Start(computation=p, cancellationToken=cancellationToken) member x.StartImmediate() = - x.StartWith(AsyncStarter.asyncStartImmediate) + let p = x.PrepareStart() + Async.StartImmediate(computation=p, cancellationToken=cancellationToken) member _.Post message = mailbox.Post message diff --git a/tests/fsharp/core/controlMailbox/test.fsx b/tests/fsharp/core/controlMailbox/test.fsx index fc8a1cc7aea..31eed776a9b 100644 --- a/tests/fsharp/core/controlMailbox/test.fsx +++ b/tests/fsharp/core/controlMailbox/test.fsx @@ -66,6 +66,14 @@ module MailboxProcessorBasicTests = 100 + check + "c32398u6: MailboxProcessor null" + (let mb1 = new MailboxProcessor(fun inbox -> async { return () }) + mb1.StartImmediate(); + 100) + 100 + + check "c32398u7: MailboxProcessor Receive/PostAndReply" (let mb1 = new MailboxProcessor>(fun inbox -> async { let! msg = inbox.Receive()