Do you have a reply channel in the post code? Do all lines of code in the handler have replies?
To me, it sounds like it's waiting for a reply that isn't coming. But, that's just a guess. If you replace PostAndReply with TryPostAndReply, does it still give you the error?
To me, it sounds like it's waiting for a reply that isn't coming. But, that's just a guess. If you replace PostAndReply with TryPostAndReply, does it still give you the error?
Thanks - my implementation uses the approach shown by Matthew Podwysocki in [link:codebetter.com] which as I read it provides all that is needed. (of course, I'm still trying to get everything straight in my head, so I may not be following it properly - particularly since it doesn't work.[:)])
Thanks to Brian's direction, I can now try to provide my code:
The calling code looks like:
Thanks,
--Don
Thanks to Brian's direction, I can now try to provide my code:
//RequestGate manages a semaphore. The Semaphore is released when the acquiring object is disposed of
//no explicit release is required.
type RequestGate(n:int) =
let semaphore = new Semaphore(initialCount=n, maximumCount=n)
member x.AcquireAsync(?timeout) =
async {let! ok = Async.AwaitWaitHandle(semaphore,?millisecondsTimeout = timeout)
if ok then
return
{new System.IDisposable with
member x.Dispose() =
semaphore.Release() |> ignore }
else
log.Error "Semaphore failure"
return! failwith "couldn't acquire a semphore"
}
let pageRequestGate = new RequestGate(8)
// Curry the arguments
let curry4 f x y z r = f ( x, y, z, r )
let curry3 f x y z = f ( x, y, z )
// Asynchronous post
let (<--) (m:_ MailboxProcessor) msg = m.Post msg
// Post and reply operator
let (<->) (m:_ MailboxProcessor) msg = m.TryPostAndReply(fun replyChannel -> msg replyChannel)
//PipelineHandler implements a Mailbox processor that initiates a new thread for each URL to
//be processed. It runs under the control of a semaphore (pageRequestGate) to limit the number of
//pages being processed at one time.
//runPipeline is a dependency injection for XYZZYAsyncPipelineManager
type PipelineHandler (runPipeline : IDisposable -> string -> string -> MarketType -> PipelineWebProcessResult list ) =
let rec runPipe =
MailboxProcessor.Start(fun inbox ->
let rec waitForMsg () =
async {use! pageLimit = pageRequestGate.AcquireAsync()
let! msg = inbox.Receive()
let! _ =
async{
match msg with
| CallMsg (uri, parentUri, market, replyChannel) ->
let urlList = runPipeline (pageLimit : IDisposable) (uri : string) (parentUri : string) (market : MarketType)
try
replyChannel.Reply(urlList)
with
| _ as e -> Console.WriteLine e.Message
Console.WriteLine ("Call with Reply: " + uri)
| CallMsgNoReply (uri, parentUri, market) ->
runPipeline (pageLimit : IDisposable) (uri : string) (parentUri : string) (market : MarketType)
|> ignore
Console.WriteLine ("Call without Reply: " + uri)
| _ -> failwith "Invalid Message"
return! waitForMsg()
} |> Async.StartChild
return! waitForMsg()
}
waitForMsg ())
member x.ProcessPageWithReply (uri : string) (parentUri : string) (market : MarketType) =
runPipe <-> curry4 CallMsg uri parentUri market
member x.ProcessPageWithoutReply (uri : string) (parentUri : string) (market : MarketType) =
runPipe <-- curry3 CallMsgNoReply uri parentUri market
The calling code looks like:
let documentPipelineHandler = new PipelineHandler (XYZZYAsyncPipelineManager)
let rec processDocTree (uri : string) (parentUri : string) (market : MarketType) =
if (uri.ToLower().EndsWith(".doc")) then
documentPipelineHandler.ProcessPageWithoutReply uri parentUri market
|> ignore
else
let resList = documentPipelineHandler.ProcessPageWithReply uri parentUri market
match resList with
| Some(rList) ->
for res in rList do
match res with
| Page (x, y, z) ->
processDocTree x y z
| EmptyPage -> ()
| None -> ()
Thanks,
--Don
Topic tags
- f# × 3663
- compiler × 263
- functional × 199
- websharper × 120
- c# × 119
- classes × 96
- web × 94
- book × 84
- .net × 82
- async × 72
- parallel × 43
- server × 43
- parsing × 41
- testing × 41
- asynchronous × 30
- monad × 28
- ocaml × 26
- tutorial × 26
- haskell × 25
- workflows × 22
- html × 21
- linq × 21
- introduction × 19
- silverlight × 19
- wpf × 19
- fpish × 18
- collections × 14
- pipeline × 14
- templates × 12
- monads × 11
- opinion × 10
- reactive × 10
- plugin × 9
- scheme × 9
- sitelets × 9
- solid × 9
- basics × 8
- concurrent × 8
- deployment × 8
- how-to × 8
- python × 8
- complexity × 7
- javascript × 6
- jquery × 6
- lisp × 6
- real-world × 6
- workshop × 6
- xaml × 6
- conference × 5
- dsl × 5
- java × 5
- metaprogramming × 5
- ml × 5
- scala × 5
- visual studio × 5
- formlets × 4
- fsi × 4
- lift × 4
- sql × 4
- teaching × 4
- alt.net × 3
- aml × 3
- enhancement × 3
- list × 3
- reflection × 3
- type provider × 3
- blog × 2
- compilation × 2
- computation expressions × 2
- corporate × 2
- courses × 2
- cufp × 2
- enterprise × 2
- entity framework × 2
- erlang × 2
- events × 2
- f# interactive × 2
- fsc × 2
- google maps × 2
- html5 × 2
- http × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- kendo × 2
- keynote × 2
- mvc × 2
- numeric × 2
- obfuscation × 2
- oop × 2
- packaging × 2
- pattern matching × 2
- pipelines × 2
- rx × 2
- script × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- type × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- addin × 1
- agents × 1
- agile × 1
- alter session × 1
- android × 1
- anonymous object × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net mvc × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- b-tree × 1
- bistro × 1
- bug × 1
- camtasia studio × 1
- canvas × 1
- class × 1
- client × 1
- clojure × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- combinator × 1
- confirm × 1
- constructor × 1
- continuation-passing style × 1
- coords × 1
- coursera × 1
- csla × 1
- css × 1
- current_schema × 1
- data × 1
- database × 1
- declarative × 1
- delete × 1
- dhtmlx × 1
- discriminated union × 1
- distance × 1
- docs × 1
- documentation × 1
- dol × 1
- domain × 1
- du × 1
- duf-101 × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- error × 1
- etw × 1
- euclidean × 1
- event × 1
- example × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- fantomas × 1
- fear × 1
- float × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- function × 1
- functional style × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- google × 1
- group × 1
- hash × 1
- history × 1
- hosting × 1
- httpcontext × 1
- https × 1
- hubfs × 1
- ie 8 × 1
- if-doc × 1
- inheritance × 1
- installer × 1
- interpreter × 1
- io × 1
- ios × 1
- ipad × 1
- kendochart × 1
- kendoui × 1
- learning × 1
- licensing × 1
- macro × 1
- macros × 1
- maps × 1
- markup × 1
- marshal × 1
- math × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- multidimensional × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- nested × 1
- nested loops × 1
- node × 1
- object relation mapper × 1
- object-oriented × 1
- offline × 1
- option × 1
- orm × 1
- osx × 1
- owin × 1
- paper × 1
- parameter × 1
- performance × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- programming × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- ptvs × 1
- quant × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- real-time × 1
- reference × 1
- restful × 1
- round table × 1
- runtime × 1
- scriptcs × 1
- scripting × 1
- service × 1
- session-state × 1
- sitelet × 1
- sqlentityconnection × 1
- stickynotes × 1
- stress × 1
- strong name × 1
- structures × 1
- tdd × 1
- template × 1
- tracing × 1
- tsunamiide × 1
- type inference × 1
- type providers × 1
- typescript × 1
- upload × 1
- vb × 1
- vb.net × 1
- vector × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- visualstudio × 1
- web api × 1
- webapi × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- xml × 1
- zarovizsga × 1
|
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us |
Built with WebSharper |
Now when I run it, I get an exception of 'multiple waiting reader continuations for mailbox' that appears to occur after the first PostAndReply. There is some confusion about exactly when the error is occurring as I've had a devil of a time tracing execution. There are additional requests for processing that do not require a reply being added to the queue (none have fired at the point of the exception) and I may be getting the error during acquisition of a semaphore - very confusing.
At the exception, I get the following on the console:
System.Transactions Critical: 0 : <TraceRecord xmlns="<A href="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord">http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord</A>" Severity="Critical"> <TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier> <Description>Unhandled exception</Description> <AppDomain>PMSA_AdminUI.vshost.exe</AppDomain> <Exception> <ExceptionType>System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType> <Message>multiple waiting reader continuations for mailbox</Message> <StackTrace> at <StartupCode$FSharp-Core>.$Control.-ctor@1780-1.Invoke(AsyncParams`1 args) at <StartupCode$FSharp-Core>.$Control.AwaitWaitHandle@1240-3.Invoke(Unit unitVar0) at <A href="mailto:Microsoft.FSharp.Control.AsyncBuilderImpl.loop@551-38(FSharpFunc`2">Microsoft.FSharp.Control.AsyncBuilderImpl.loop@551-38(FSharpFunc`2</A> action) at Microsoft.FSharp.Control.AsyncBuilderImpl.Trampoline.Protect(FSharpFunc`2 firstAction) at <StartupCode$FSharp-Core>.$Control.AwaitWaitHandle@1237-2.Invoke(Object state, Boolean timedOut) at System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context(Object state, Boolean timedOut) at System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context_f(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(Object state, Boolean timedOut) </StackTrace> <ExceptionString>System.Exception: multiple waiting reader continuations for mailbox at <StartupCode$FSharp-Core>.$Control.-ctor@1780-1.Invoke(AsyncParams`1 args) at <StartupCode$FSharp-Core>.$Control.AwaitWaitHandle@1240-3.Invoke(Unit unitVar0) at <A href="mailto:Microsoft.FSharp.Control.AsyncBuilderImpl.loop@551-38(FSharpFunc`2">Microsoft.FSharp.Control.AsyncBuilderImpl.loop@551-38(FSharpFunc`2</A> action) at Microsoft.FSharp.Control.AsyncBuilderImpl.Trampoline.Protect(FSharpFunc`2 firstAction) at <StartupCode$FSharp-Core>.$Control.AwaitWaitHandle@1237-2.Invoke(Object state, Boolean timedOut) at System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context(Object state, Boolean timedOut) at System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context_f(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(Object state, Boolean timedOut) </ExceptionString> </Exception> </TraceRecord>I'm looking for ideas or thoughts on what might be happening. I'd be happy to post my code, but I can't seem to figure out how to make it tolerably presentable (must be missing something obvious ). In any case, given the AwaitWaitHandle in the traceback, does this seem to imply an issue with my semaphore? I've tried several changes (including creating a new semaphore on each call) to no avail.
Thoughts appreciated.
--Don