使用不带返回类型的yield

时间:2013-12-31 11:40:13

标签: c# .net asynchronous yield feedback

我有一个很长的循环过程:

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

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

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

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

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

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

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

5 个答案:

答案 0 :(得分:12)

您想要的语言功能称为 coroutine (或者更准确地说,是 semicoroutine ,但我们不要迂腐。)C#迭代器块是一种弱形式的协程。我建议不要因为你想要协程而制作“虚拟”序列。

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

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

答案 1 :(得分:11)

简而言之,

yield return必须返回一些内容。

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

Process方法的返回类型应为IEnumerableIEnumerable<T>IEnumeratorIEnumerator<T>。如果您真的想使用objects,则可以返回虚拟yield

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

答案 2 :(得分:9)

正如其他人已经回答的那样,不是没有办法,但为什么不简单地使用回调FuncAction或其他东西让被叫者与你的循环互动?< / p>

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

或使用其他类型的事件处理,通常用于此类事件。

答案 3 :(得分:6)

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

class ProgressInfo { ... }
...
yield return new ProgressInfo() { ... };

然后,调用者将foreach对结果进行操作并对其进行操作。

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

答案 4 :(得分:3)

不,不可能。只有当返回类型为IEnumerableIEnumerator时,编译器才会为您生成迭代器。

解决方法是返回一些值并更改方法的返回类型以使编译器满意。

相关问题