使用不带返回类型的yield

Vin*_*rgh 15 .net c# asynchronous feedback yield

我有一个很长的循环过程,如下所示:

public void Process()
{
    bool done = false;
    do {
        //do stuff
    }while (!done);
}
Run Code Online (Sandbox Code Playgroud)

我想切入比特并让调用例程在某种UI中显示我的进度.它是一个类库,因此调用者可能是任何东西(Console App,WinForms,WebApp,...).

如果我能做的话,这将是最简单的:

public void Process()
{
    bool done = false;
    do {
        //do stuff
        yield return;
    }while (!done);
}
Run Code Online (Sandbox Code Playgroud)

因此调用者可以继续调用该方法,直到完成为止.

这更像是BackgroundWorker的工作,但对于控制台应用来说这似乎是"错误的"......我不会总是需要多线程.或者是吗?我的意思是,是的,我可以让控制台的主线程等待它完成.

我的问题是:我可以使用"收益回报"的"零碎"延迟执行功能而不实际返回某些内容吗?

Eri*_*ert 12

你想要的语言特征叫做协程(或者更确切地说,是一个半自由的,但是不要迂腐.)C#迭代器块是一个弱形式的协程.我建议不要因为你想要协程而制作"虚拟"序列.

awaitC#5中的运算符也是协程的一种形式,可能更符合您期望的解决方案,特别是如果您的操作在逻辑上是异步,高延迟操作.C#5中有异步协同进程报告的标准模式; 我会先阅读这篇文章:

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


Jak*_*cki 11

简而言之,没有.

yield return 必须归还一些东西.

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

Process方法应该有返回类型IEnumerable,IEnumerable<T>,IEnumerator,或IEnumerator<T>.objects如果你真的想使用,你可能会返回虚拟yield.

您可能希望调查向调用者报告进度的不同方法.


Mic*_*haC 9

前面已经有人回答说,没有,这不是要走的路,但你为什么不干脆用一个回调FuncAction什么的,让被叫方与循环互动?

public void Process(Action callback)
{
    bool done = false;
    do {
        //do stuff
        callback();
    }while (!done);
}
Run Code Online (Sandbox Code Playgroud)

或者使用一些其他类型的事件处理,通常用于这样的事情.


usr*_*usr 6

您说您希望调用者响应方法的进度.您可以返回进度信息:

class ProgressInfo { ... }
...
yield return new ProgressInfo() { ... };
Run Code Online (Sandbox Code Playgroud)

然后呼叫者将对foreach结果进行处理并对其进行操作.

这比调用者检查全局可变状态要好得多.这是一个功能性解决方案.