Hacker News new | past | comments | ask | show | jobs | submit login

Eh, syntactically async rust is the exact same as C#. It's all task based concurrency.

Now, lifetimes attached to function signatures is definitely a problem.




Not really. C#'s Task/Task<T> are based on background execution. Once something is awaited, control is returned to the caller. OTOH, Rust's Future<T> is, by default, based on polling/stepping, a bit like IEnumerable<T> in C#; If you never poll/await the Future<T>, it never executes. Executor libraries like Tokio allow running futures in the background, but that's not built-in.


How do you imagine async works otherwise? Also, in case you misunderstand how polling works in practice in rust, it's not polling in the traditional web development sense where it polls every 5 ms to check if a future is completed (although you can do this if you want to for some reason). There are typically "wakers" that are "awoken" by the os when data is ready and when they are "awoken" then they poll. And since they are only awoken by the OS when the information is ready it really never has to poll more than once unless there are multiple bundled futures.


I don't want to "well actually" the "well actually", but I think you missed the word syntactically.

> C#'s Task/Task<T> are based on background execution. Once something is awaited, control is returned to the caller.

Async/await in any language happens in the background.

What happens during a Task.Yield() (C#)? The task is yielded to the another awaiting task in the work queue. Same as Rust.

> OTOH, Rust's Future<T> is, by default, based on polling/stepping,

The await syntax abstracts over Future/Stream polling. The real difference is that Rust introduced the Future type/concept of polling at all (which is a result of not having a standard async runtime). There is a concept of "is this task available to proceed on" in C# too, it's just not exposed to the user and handled by the CLR.


> Task.Yield()

In c# you probably never call yield.


Yield in C# is frequently used for the same reasons as in Rust, although implementation details between fine-grained C# Tasks and even finer grained Rust Futures aggregated into large Tasks differ quite a bit.

Synchronous part of an async method in C# will run "inline". This means that should there be a computationally expensive or blocking code, a caller will not be able to proceed even if it doesn't await it immediately. For example:

    var ptask = Primes.Calculate(n); // returns Task<ulong[]>
    // Do other things...right?
    // Why are we stuck calculating the primes then?
    Console.WriteLine("Started.");
In order for the .Calculate to be able to continue execution "elsewhere" in a free worker thread, it would have to yield.

If a caller does not control .Calculate, the most common (and, sadly, frequently abused) solution is to simply do

    var task = Task.Run(Primes.Calculate);
    // Do something else
    var text = string.Join(',', await task);
If a return signature of a delegate is also Task, the return type will be flattened - just a Task<T>, but nonetheless the returned task will be a proxy that will complete once the original task completes. This successfully deals with badly behaved code.

However, a better solution is to instead insert `Task.Yield()` to allow the caller to proceed and not be blocked, before continuing a long-running operation:

    var ptask = Primes.Calculate(n); // returns Task<ulong[]>
    // Successfully prints the message
    Console.WriteLine("Started.");


    static async Task<int[]> CalculatePrimes(int n)
    {
        await Task.Yield();
        // Continue execution in a free worker thread
        // If the caller immediately awaits us, most likely
        // the caller's thread will end up doing so, as the
        // continuation will be scheduled in the local queue,
        // so it is unlikely for the work item to be stolen this
        // quickly by another worker thread.
    }


It was just an example. In practice, you're right.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: