Hide this comment

Not sure if this is what you are looking for, but the following will spawn off an asynchronous background thread to run your external process and do some work, without blocking the GUI thread. Fill out AsyncRunProcess, as appropriate (supply args, etc.).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
type System.Diagnostics.Process with
    member this.AsyncWaitForExit( ?millisecondsTimeout ) =
        async {
            use h = new System.Threading.EventWaitHandle( false, System.Threading.EventResetMode.ManualReset )
            h.SafeWaitHandle <- new Microsoft.Win32.SafeHandles.SafeWaitHandle( this.Handle, true )
            match millisecondsTimeout with
            | Some(ms)  -> return! Async.AwaitWaitHandle( h, ms )
            | None      -> return! Async.AwaitWaitHandle( h )
            }

let AsyncRunProcess cmd =
    async {
        use proc = new System.Diagnostics.Process()
        proc.StartInfo.FileName <- cmd
        proc.Start() |> ignore
        let! b = proc.AsyncWaitForExit()
        ()
    }

let AsyncDoSomeWork() =
    async {
        do! AsyncRunProcess @"c:\windows\system32\ping.exe"
        // do some other work here
        }

let main() =
    AsyncDoSomeWork()
    |> Async.Start

main()
By on 4/7/2010 9:05 PM ()Reply
Hide this comment

Thanks jhugard! It's not going to work for this particular piece of code, but that is some really good stuff. I'm going to use that elsewhere.

By on 4/8/2010 10:28 AM ()Reply
Hide this comment

Be sure to check out "F# async on the client side"

[link:lorgonblog.spaces.live.com]

which isn't immediately relevant to this issue but shows some good general advice about keeping the UI thread free.

By on 4/8/2010 11:25 AM ()Reply
Hide this comment

F# programs per-se don't have a message pump, unless you're dong low-level Windows coding w/interop, are a Winforms, or are a WPF app, and in the latter case WPF has a seperate thread for its pump so you never need to do this. This seems like a weird pattern, co-mingling the lifetime of the created process and your own in such a tightly-coupled Windows-specific way.

What exactly are you trying to accomplish? What process are you starting and why do you need to mess w/message-pumps?

But I see you've posted about using GTK and Qt w/f#, so I guess you're just some kind of sick thrill seeker :)

By on 4/7/2010 7:27 PM ()Reply
Hide this comment

Thanks "anotheraccount"! Unfortunately, this thrill is from my day job. I migrated a massive client/server desktop application from C to C++ to C++/CLI, so that is why you see the message pumps. The move to C++/CLI wasn't bad at all and with it built on .NET, we can replace chunks of the application with .NET code libraries built with C# and F#. Well, not quite yet F#. After we move to Visual Studio 2010, we may get team buy-in to use F#.

I was struggeling to make some changes to the Win32 CreateProcess() function call, so I switched over to creating the process with System.Diagnostics.Process, but ended up creating a bug that locks up the GUI because of a Process.WaitForExit() call. Getting rid of that call and putting the message pump back in place restores the previous behavior. C++/CLI like so, where p is an instance of Process^:

MSG msg;

while(!p->HasExited)

{

Thread::Sleep(TIMEOUT); // so the thread doesn't eat up 100% CPU in this loop

while(PeekMessage(&msg, (HWND)0, 0, 0, PM_REMOVE))

w_msg(&msg);

}

return p->ExitCode;

Sorry for all the C++/CLI in a F# forum. I promise to post some more F# blogs when I get a chance. If only I could find a day job that allowed me to do more F#...

By on 4/8/2010 10:25 AM ()Reply
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper

Logging in...