Please tell me how I can pause the console window when running the program in F#.
open System
let myList = [0..9]
let myFunction =
for n in myList do
Console.WriteLine(n)
myFunction
I am guessing that you want the console to display the output after the program execution finishes.
You could put this line in the end of your snippet
Console.ReadKey() |> ignore
to 'pause' the console in that sense.
You may consider to wrap the pause function in compiler directives, since you probably don't want to have the same effect in release code.
(* your code here *)
#if DEBUG
System.Console.ReadKey(true) |> ignore
#endif
// When running in debug mode and using Visual Studio to run the program,
// one may miss the results as the program runs to the end and exists.
// Since running normally, i.e. Visual Studio Ctrl-F5, will add an pause
// automatically the pause is only shown when in debug mode.
let pause () =
match System.Diagnostics.Debugger.IsAttached with
| true ->
printfn "\nPress any key to continue."
System.Console.ReadKey(true) |> ignore
| false -> ()
pause ()
Related
I'm trying to scrape some websites that need to run their JavaScript before the document has all the data I'm interested in. I'm trying to open a WebBrowser and wait for the document to load, but I can't get the data when I try to switch back to the thread the WebBrowser is on. Trying to run it without switching back to the thread gives casting errors. = (
What's stopping the async from switching threads? How do I fix this problem?
Script
open System
open System.Windows.Forms
open System.Threading
let step a = do printfn "%A" a
let downloadWebSite (address : Uri) (cont : HtmlDocument -> 'a) =
let browser = new WebBrowser()
let ctx = SynchronizationContext.Current
browser.DocumentCompleted.Add (fun _ ->
printfn "Document Loaded" )
async {
do step 1
do browser.Navigate(address)
do step 2
let! _ = Async.AwaitEvent browser.DocumentCompleted
do step 3
do! Async.SwitchToContext ctx
do step 4
return cont browser.Document }
let test =
downloadWebSite (Uri "http://www.google.com") Some
|> Async.RunSynchronously
Output
>
1
2
Document Loaded
3
# It just hangs here. I have to manually interrupt fsi.
- Interrupt
>
4
The problem with your approach is that RunSynchronously blocks the thread that you are trying to use to run the rest of the asynchronous computation using Async.SwitchToContext ctx.
When using F# Interactive, there is one main thread which runs in the F# Interactive and handles the user interactions. This is the thread that can use Windows Forms controls, so you correctly create WebBrowser outside of async. The waiting for DocumentCompleted happens on a thread pool thread (which runs the async workflow), but when you try to switch back to the main thread, it is already blocked by Async.RunSynchronously.
You can avoid blocking the thread by running a loop that calls Application.DoEvents to process events on the main thread (which will also allow it to run the rest of your async). Your downloadWebSite stays the same, but now you wait using:
let test =
downloadWebSite (Uri "http://www.google.com") Some
|> Async.Ignore
|> Async.StartAsTask
while not test.IsCompleted do
System.Threading.Thread.Sleep(100)
System.Windows.Forms.Application.DoEvents()
This is a bit of a hack - and there might be a better way of structuring this if you do not really need to wait for the result (e.g. just return a task and wait before running the next command), but this should do the trick.
I found a variety of SO questions on this but couldn't figure out an F# solution. I need to block wait for an event to fire at me to check the data it returns. I am using Rx to receive event 3 times:
let disposable =
Observable.take 3 ackNack
|> Observable.subscribe (
fun (sender, data) ->
Console.WriteLine("{0}", data.AckNack)
Assert.True(data.TotalAckCount > 0u)
)
I would like to either turn results into a list, so they can be checked later on by the test framework (xUnit), or wait for all 3 events to complete and pass the Assert.True.
How would I wait for 3 events to fire before continuing? I can see there's an Observable.wait other sources suggest Async.RunSynchronously.
I think the easiest option is to use Async.AwaitObservable function - sadly, this is not yet available in the F# core library, but you can get it from the FSharpx.Async package, or just copy the function soruce from GitHub.
Using the function, you should be able to write something like:
let _, data =
Observable.take 3 ackNack
|> Async.AwaitObservable
|> Async.RunSynchronously
Console.WriteLine("{0}", data.AckNack)
Assert.True(data.TotalAckCount > 0u)
I'm using the NUnit testing technique suggested in the yet to be released book "F# Deep Dives Version 12" (Sec. 2.2 "Adding Tests")
The code below executes fine compiled or interactive with MEMOIZE defined/undefined. However, executing the unit test from the GUI NUnit works fine with MEMOIZE undefined, but it fails with a "Null Reference Exception" when MEMOIZE is defined. Notice memorize() uses a Closure. I'm suspecting the exception is happening because some initialization code generated by the compiler is not getting executed when NUnit starts up. What do you think?
open System
open System.Collections.Generic
open NUnit.Framework
open FsUnit
let memoize (f: 'T -> 'U) =
let t = new Dictionary<'T, 'U>(HashIdentity.Structural)
fun n ->
if t.ContainsKey n then t.[n]
else let res = f n
t.Add(n, res)
res
//TODO: Insure J>0 & K>0 & J<K
let isMult =
#if MEMOIZE
memoize (fun (j,k) -> k % j = 0)
#else
(fun (j,k) -> k % j = 0)
#endif
type ``Given the isMult function``() =
[<TestCase(3,1,false)>]
[<TestCase(3,2,false)>]
[<TestCase(3,3,true)>]
[<TestCase(5,10,true)>]
[<TestCase(3,15,true)>]
[<TestCase(5,13,false)>]
[<TestCase(5,15,true)>]
member t.``the result is calculated correctly``(j, k, expected) =
let actual = isMult (j,k)
actual |> should equal expected
UPDATE:
The standalone NUnit application is version 2.6.3.13283.
"FinnNk" gave me an idea! I installed Nuget package "NUnitTestAdapter". Now I can test directly within VS 2013. No surprises, though. I get all tests 'green' when MEMORIZE is undefined and all tests 'red' when it is defined.
The exception is still the same: "Null Reference Exception". However, now that it executes in the IDE, I can have the debugger stop on the exception. All I can determine so far at the breakpoint is that it needs the symbols from:
C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.pdb
I installed the new VS 2015 Preview Edition. Nothing different happens in that environment. Now that .NET Framework is open source, maybe I can zero the debugger precisely on the problem with the source code for "mscorlib".
Are you running your NUnit tests in multiple threads? Normal dictionary is not thread-safe so weird things can happen. How about if you use ConcurrentDictionary, will it give the same result?
let memoize (f: 'T -> 'U) =
let t = System.Collections.Concurrent.ConcurrentDictionary<'T, 'U>()
fun n -> t.GetOrAdd(n, f)
I have a COM object, which I connect to, and I should recieve an event, which would confirm that connection is established. I write code and test it in F# interactive, and for some reason it wouldn't catch COM events when I use Async.RunSynchronously.
/// This class wraps COM event into F# Async-compatible event
type EikonWatcher(eikon : EikonDesktopDataAPI) =
let changed = new Event<_>()
do eikon.add_OnStatusChanged (fun e -> changed.Trigger true)
member self.StatusChanged = changed.Publish
/// My method
let ``will that connection work?`` () =
let eikon = EikonDesktopDataAPIClass() :> EikonDesktopDataAPI // create COM object
let a = async {
let watcher = EikonWatcher eikon // wrap it
eikon.Initialize() |> ignore // send connection request
let! result = Async.AwaitEvent watcher.StatusChanged // waiting event
printfn "%A" result // printing result
return result
}
// I use either first or second line of code, not both of them
Async.Start (Async.Ignore a) // does not hang, result prints
Async.RunSynchronously (Async.Ignore) a // hangs!!!
/// Running
``will that connection work?`` ()
At the same time, code works perfectly well with RunSynchronously when I insert it into console app.
What should I do so that to prevent that nasty behavior?
The code we write under within a single Thread (as in STA) feels like it is made of independant pieces each having their own life, but this is actually a fallacy : everything is mediated under a common event loop, which "linearizes" the various calls.
So everything we do, unless explicitely spoecified otherwise, is essentially single threaded and you can not wait for yourself without creating a deadlock.
When you specify Async.Start it does start a new, independant computation which runs on its own, a "thread".
Whereas When you call runsynchronously, it awaits on the same 'thread'.
Now if the event you are waiting, which feels like an independant thing, is actually 'linearized' by the same event loop, you are actually waiting for yourself, hence the deadlock.
Something useful if you want to wait "asynchronously", (aka wait for an event, but not actually block and leave the opportunity for any other task to perform work) you can use the following code within your async block :
async {
....
let! token = myAsyncTask |> Async.StartChild
let! result = token
....
}
Knowing an RPC call to a server method that returns unit is a message passing call, I want to force the call to be asynchronous and be able to fire the next server call only after the first one has gone to the server.
Server code:
[<Rpc>]
let FirstCall value =
printfn "%s" value
async.Zero()
[<Rpc>]
let SecondCall() =
"test"
Client code:
|>! OnClick (fun _ _ -> async {
do! Server.FirstCall "test"
do Server.SecondCall() |> ignore
} |> Async.Start)
This seems to crash on the client since returning unit, replacing the server and client code to:
[<Rpc>]
let FirstCall value =
printfn "%s" value
async { return () }
let! _ = Server.FirstCall "test"
Didn't fix the problem, while the following did:
[<Rpc>]
let FirstCall value =
printfn "%s" value
async { return "" }
let! _ = Server.FirstCall "test"
Is there another way to force a message passing call to be asynchronous instead?
This is most definitely a bug. I added it here:
https://bugs.intellifactory.com/websharper/show_bug.cgi?id=468
Your approach is completely legit. Your workaround is also probably the best for now, e.g. instead of returning Async<unit> return Async<int> with a zero and ignore it.
We are busy with preparing the 2.4 release due next week and the fix will make it there. Thanks!
Also, in 2.4 we'll be dropping synchronous calls, so you will have to use Async throughout for RPC, as discussed in https://bugs.intellifactory.com/websharper/show_bug.cgi?id=467 -- primarily motivated by new targets (Android and WP7) that do not support sync AJAX.