Suppose that I have the following code:
namespace Library1
open System.Threading.Tasks
open System.Threading
open System.Runtime.Remoting.Messaging
open System
type public Class1() =
    let printThread (message) = 
        printfn "%s %A" message Thread.CurrentThread.ManagedThreadId
    let bar = 
        printThread ("first bar")
        async { 
            printThread ("first async")
            do! Async.Sleep(1000)
            printThread "last async"
        }
    member this.X() =  bar
I would like to use this class and invoke X from C#. The problem is X returns an Async<'T>. However, it is bad practice to expose F# specific types. So best practice is to return a Task. However Async.StartAsTask is kind of problematic since it will cause the code run in a seperate thread. What I want is I want to return a Task but also it should behave as Async.StartImmediate. Thus the non async part of the code should run in the original main thread. Here I assume I run it from UI thread so that all calls will return the same thread ID. In other words I want a Async.StartImmediate but returning a task. Is this achieavable ?
You can turn Async<'T> into Task<'T> using the Async.StartAsTask<'T> method. 
I'd generally recommend making things easy for the C# users and extend the F# implementation with an additional method that returns Task<'T>. Following the usual naming convention, you can call the F# version AsyncFoo and the C#-friendly version FooAsync. 
Looking at your example, I'd go with something like this:
type public Class1() =
    let printThread (message) = 
        printfn "%s %A" message Thread.CurrentThread.ManagedThreadId
    let bar = 
        printThread ("first bar")
        async { 
            printThread ("first async")
            do! Async.Sleep(1000)
            printThread "last async"
        }
    member this.AsyncFoo() =  bar
    /// Expose C#-friendly asynchronous method that returns Task
    member this.FooAsync() = Async.StartAsTask(bar)
    /// Expose C#-friendly asynchronous method that returns Task
    /// and takes cancellation token to support cancellation...
    member this.FooAsync(cancellationToken) = 
      Async.StartAsTask(bar, ?cancellationToken=cancellationToken)
                        This Works exactly as I want (unlike the question this version returns an int as well which is plus):
type public Class1() = 
    let printThread (message) = printfn "%s %A" message Thread.CurrentThread.ManagedThreadId
    let bar = 
        printThread ("first bar")
        async { 
            printThread ("first async")
            do! Async.Sleep(1000)
            printThread "last async"
            return 1232
         }
    member this.convertToTask<'T> (asyn : Async<'T>) = 
       let tcs1 = new TaskCompletionSource<'T>()
       let t1 = tcs1.Task
       Async.StartWithContinuations
        (
          asyn 
          , (fun (k) -> tcs1.SetResult(k)), (fun exn -> tcs1.SetException(exn)), fun exn -> ())
        t1
    member this.X() : Task<int> =  (bar |> this.convertToTask)
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With