我有以下代码(简化):
IEnumerable MyFunc(...){
IAsyncResult res = mSocket.BeginReceive(mReceptionArray, 0, pNbBytes, SocketFlags.None, null, null);
while (!res.IsCompleted){
yield return new WaitForFixedUpdate();
}
}
可以这样使用:
foreach(object o in MyFunc());
当然,编译器抱怨因为o
从未使用过。有没有办法解决这个问题?
修改
foreach在协程中执行。我需要阻止协程的执行,直到我从服务器接收数据。我可以使用常规的Receive(),但这会阻止所有其他协同程序,我不能这样做:有很多其他协同程序在运行,用Receive或EndReceive阻止它会阻止它们。
无论如何,这是不忙碌等待。
任何重构代码的建议都非常受欢迎,我对C#不是很有经验。
答案 0 :(得分:3)
我会写一个新的扩展方法来使用序列并忽略结果。例如:
// TODO: Documentation
public static void ConsumeSequence<T>(this IEnumerable<T> source)
{
// TODO: Argument validation
using (var iterator = source.GetEnumerator())
{
while (iterator.MoveNext())
{
// Deliberate no-op
}
}
}
然后在调用代码中清楚你正在做什么,并且你故意只是消耗序列并忽略结果。
就像六个变量一样,你的序列是否合适并不是很清楚,但是如果你 只想消耗一个序列,那就是我要做的。
答案 1 :(得分:1)
在看到你在做什么之后,我真的不认为这是你想要的。您已使用foreach
语句实现了忙等待。你已经声明这样做是为了不阻止其他协同程序,但我看不出忙等待循环也不会阻止其他协同程序。
Every .Begin*
有一个corresponding .End*
,可以优雅地暂停执行该线程,直到异步操作完成。
// Suspend execution until the receive operation completes
mSocket.EndReceive(res);
答案 2 :(得分:1)
foreach(object o in MyFunc())
doNothing(o); // avoiding warning
并创建一个空白方法:
void doNothing(object o){ }
答案 3 :(得分:1)
以下是Javad_Amiry答案的一个变体(顺便说一句我加了1个):
public static void Unused<T>(this T value) { }
因为它是一种扩展方法,您可以使用以下语法从任何地方调用它:
foreach (object o in MyFunc())
o.Unused();
现在,如果有人想知道,我确实尝试在其上方添加[Conditional("NEVER_COMPILE_ME")]
,但遗憾的是,这会导致警告回来。
顺便说一句,根据我对Unity的经验,yield return null
根本不会杀死协程。但是你的代码实际上是一个忙碌的等待,因为你没有给Unity提供协同程序 - 你自己运行它。使用您的代码,您构建的WaitForFixedUpdate
对象只会以o
(或null
所做的那样)出现,您可以忽略它并再次转向; Unity永远不会看到它。如果你想要Unity WaitForFixedUpdate
或其他任何东西,你必须通过调用StartCoroutine(MyFunc())
来控制协程。它是MonoBehaviour
上的一个实例方法,只要MonoBehaviour
保持启用状态,协程就会运行完成。希望澄清:)
var subCoroutine = StartCoroutine(MyFunc());
yield return subCoroutine;
或等效的单行版本:
yield return StartCoroutine(MyFunc());
这将告诉Unity在继续使用此协程之前等待其他协同程序完成。
如果您需要稍低的级别,也可以这样做:
foreach (object o in MyFunc())
yield return o;
答案 4 :(得分:0)
您的代码看起来很奇怪 - 为什么在您立即阻塞时仍然无法在套接字上使用异步I / O方法,直到它完成为止?
这将取消您的警告:
#pragma warning disable 0168
// code goes here
#pragma warning restore 0168
但是想想在你做这样的事情之前有更好的方法。见Jon的回答。
答案 5 :(得分:0)
效率最高,但肯定很短:
MyFunc().Any(x => false);