繁体   English   中英

C#foreach与Action.BeginInvoke

[英]c# foreach with Action.BeginInvoke

好吧,所以我在这里有一个问题。 这是循环。

lock (ClientLocker)
{
    Trace.WriteLine("#WriteAll: " + sm.Header);
    foreach (Client c in Clients)
    {
        if (c.LoggedIn)
        {
            Trace.WriteLine("#TryWriteTo[" + c.Id + "](" + sm.Header + ")");
            LazyAsync.Invoke(() => c.WriteMessage(sm));
        }
    }
}

这是LazyAsync

public static class LazyAsync
{
    public static void Invoke(Action a)
    {
        a.BeginInvoke(a.EndInvoke, null);
    }
}

每个Client包含一个socket ,因此我几乎无法Clone它。 问题是,当我做Invokec.WriteMessage ,因为执行被延迟,它通常会不火的第一对夫妇在列表中,并且有时实际上只火上的最后一项一大堆。

我知道这与c是在实际Invoke之前更改的引用有关,但是有办法避免这种情况吗?

进行一般的for(int i=0 etc循环似乎无法解决此问题。

有人对我该如何解决有任何想法吗?

记住,不能Clone Client

将您的c复制到本地变量,如下所示:

lock (ClientLocker)
{
    Trace.WriteLine("#WriteAll: " + sm.Header);
    foreach (Client c in Clients)
    {
        if (c.LoggedIn)
        {
            Client localC = c;
            Trace.WriteLine("#TryWriteTo[" + c.Id + "](" + sm.Header + ")");
            LazyAsync.Invoke(() => localC.WriteMessage(sm));
        }
    }
}

如果要获取更多信息,请在Web上搜索:“访问已修改的闭包”。

您的猜想是正确的:变量c由lambda表达式捕获,但直到以后才进行评估。

每当您在lambda表达式中使用循环变量时,都会弹出这种错误提示,因为循环变量的作用域是循环外部,而不是循环的每次迭代。

您可以通过在foreach循环中创建一个新的局部变量,为它分配c ,然后将该新的局部变量传递给lambda表达式来解决此问题:

lock (ClientLocker)
{
    Trace.WriteLine("#WriteAll: " + sm.Header);
    foreach (Client c in Clients)
    {
        if (c.LoggedIn)
        {
            Trace.WriteLine("#TryWriteTo[" + c.Id + "](" + sm.Header + ")");

            Client copyOfC = c;
            LazyAsync.Invoke(() => copyOfC.WriteMessage(sm));
        }
    }
}

以下是一些与StackOverflow相关的帖子:

尝试将c设置为局部变量,并在其上调用LazyAsync.Invoke ,以避免在调用发生之前由foreach循环将c重新分配给c LazyAsync.Invoke执行c.WriteMessage ,它将在c指向的任意点上调用WriteMessage ,而不是LazyAsync.Invoke(() => c.WriteMessage(sm))时的状态

foreach (Client c in Clients)
{
    if (c.LoggedIn)
    {
        Trace.WriteLine("#TryWriteTo[" + c.Id + "](" + sm.Header + ")");

        Client client = c;
        LazyAsync.Invoke(() => client.WriteMessage(sm));
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM