Sasha Babaei
Sasha Babaei

Reputation: 485

C# to F# and Interdependent Functions

I would appreciate it if someone kindly helps me with translating this into F#. Not in the class form of course: 1) If I declare ThreadProc first, ThreadProc is supposed to use thread1 and thread2 which are later defined in the main using ThreadProc in the constructors; and if I declare main first, the initialisations will use a function that is not yet defined. 2) If I declare top-level thread1 and thread2 before defining function ThreadProc (e.g., let thread1 = new Thread(fun () -> ())), then that is the version that ThreadProc will ultimately utilise rather than the one later declared in the main.

using System;
using System.Threading;

public class Example
{
    static Thread thread1, thread2;

    public static void Main()
    {
        thread1 = new Thread(ThreadProc);
        thread1.Name = "Thread1";
        thread1.Start();

        thread2 = new Thread(ThreadProc);
        thread2.Name = "Thread2";
        thread2.Start();   
    }   

    private static void ThreadProc()
    {
        Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
        if (Thread.CurrentThread.Name == "Thread1" && 
            thread2.ThreadState != ThreadState.Unstarted)
                thread2.Join();

        Thread.Sleep(4000);
        Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
        Console.WriteLine("Thread1: {0}", thread1.ThreadState);
        Console.WriteLine("Thread2: {0}\n", thread2.ThreadState);
   }
}

Upvotes: 0

Views: 149

Answers (2)

Bent Tranberg
Bent Tranberg

Reputation: 3470

This demonstrates what I was referring to in my comment. It uses ParameterizedThreadStart to pass information to the threads via an F# record.

You are responsible for making sure that the object passed in is of the same type as is expected within the thread proc. The argument to the thread proc is necessarily of type obj, so the compiler can't check the type for you. But you can create an appropriately typed shadow of args with let args = args :?> Args for convenience within the proc.

open System
open System.Threading

type Args = { Thread1: Thread; Thread2: Thread }

let threadProc (args: obj) =
    let args = args :?> Args

    printfn "\n\nCurrent Thread: %s" Thread.CurrentThread.Name

    if Thread.CurrentThread.Name = "Thread 1" && args.Thread2.ThreadState <> ThreadState.Unstarted then
        args.Thread2.Join ()

    Thread.Sleep(4000)
    Console.WriteLine( "\n\nCurrent thread: {0}", Thread.CurrentThread.Name )
    Console.WriteLine("Thread 1: {0}", args.Thread1.ThreadState)
    Console.WriteLine("Thread 2: {0}\n", args.Thread2.ThreadState)

let thread1 = new Thread(ParameterizedThreadStart(threadProc))
thread1.Name <- "Thread 1"

let thread2 = new Thread(ParameterizedThreadStart(threadProc))
thread2.Name <- "Thread 2"

let main () =
    let args = { Thread1 = thread1; Thread2 = thread2 }
    thread1.Start(args)
    thread2.Start(args)
    System.Console.ReadKey () |> ignore

do main ()

Upvotes: 1

Sasha Babaei
Sasha Babaei

Reputation: 485

I have come up with the following code. However, I would appreciate any suggestions on making it better, i.e., the smarter/shorter way and/or somehow not-using 'mutable' values:

open System
open System.Threading

let mutable thread1 = new Thread( fun () -> () )
let mutable thread2 = new Thread( fun () -> () )

let threadProc () =
    printfn "\n\nCurrent Thread: %s" Thread.CurrentThread.Name

    if ( Thread.CurrentThread.Name = "Thread 1" && 
         thread2.ThreadState <> ThreadState.Unstarted ) then 
             thread2.Join ();

    Thread.Sleep(4000)
    Console.WriteLine( "\n\nCurrent thread: {0}", 
                        Thread.CurrentThread.Name )
    Console.WriteLine("Thread 1: {0}", thread1.ThreadState)
    Console.WriteLine("Thread 2: {0}\n", thread2.ThreadState)

thread1 <- new Thread(threadProc)
thread1.Name <- "Thread 1"

thread2 <- new Thread(threadProc)
thread2.Name <- "Thread 2"

let main () = 
    thread1.Start()
    thread2.Start()
    System.Console.ReadKey () |> ignore

do main () 

Upvotes: 0

Related Questions