Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using yield without return type

I have a big long looping procedure like this:

public void Process()
{
    bool done = false;
    do {
        //do stuff
    }while (!done);
}

that I'd like to chop into bits and have the calling routine display my progress in some sort of UI. It's a class library, so the caller may be anything (Console App, WinForms, WebApp, ...).

It would be easiest if I could do:

public void Process()
{
    bool done = false;
    do {
        //do stuff
        yield return;
    }while (!done);
}

So the caller could keep calling the method until it's done.

This smells more like a job for BackgroundWorker, but that seems "wrong" for a Console App... I won't always NEED multithreading. Or does it? I mean, yeah, I could just have the console's main thread just wait for it to finish.

My question is: Can I use the "piecemeal" deferred execution functionality of "yield return" without actually returning something?

like image 565
Vincent Vancalbergh Avatar asked Dec 31 '13 11:12

Vincent Vancalbergh


People also ask

Is yield break the same as return?

It specifies that an iterator has come to an end. You can think of yield break as a return statement which does not return a value.

When using yield return in a method What should the method return type be?

The yield return statement returns one element at a time. The return type of yield keyword is either IEnumerable or IEnumerator .

Does yield break return null?

1. "yield break" breaks the Coroutine (it's similar as "return"). "yield return null" means that Unity will wait the next frame to finish the current scope. "yield return new" is similar to "yield return null" but this is used to call another coroutine.


3 Answers

The language feature you want is called a coroutine (or, more precisely, a semicoroutine, but let's not be pedantic.) C# iterator blocks are a weak form of coroutine. I recommend against making "dummy" sequences just because you want coroutines.

The await operator in C# 5 is also a form of coroutine and might more closely resemble your desired solution, particularly if your operation is logically an asynchronous, high-latency operation. There are standard patterns for progress reporting with asynchronous coroutines in C# 5; I would start by reading this:

http://blogs.msdn.com/b/dotnet/archive/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-apis.aspx

like image 87
Eric Lippert Avatar answered Sep 23 '22 01:09

Eric Lippert


In short, no.

yield return has to return something.

http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

The Process method should have a return type of IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>. You may return dummy objects if you really want to use yield.

You might want to investigate different ways to report progress to the caller.

like image 36
Jakub Konecki Avatar answered Sep 21 '22 01:09

Jakub Konecki


As already someone else answered, no that's not the way to go, but why don't you simply use a callback Func or Action or something to let the callee interact with your loop?

public void Process(Action callback)
{
    bool done = false;
    do {
        //do stuff
        callback();
    }while (!done);
}

Or use some other kind of event handling which is typically used for stuff like that.

like image 27
MichaC Avatar answered Sep 25 '22 01:09

MichaC