在调用开始之前,迭代中的值会发生变化

NLV*_*NLV -2 .net c# scope asynchronous

我在我的应用程序中有以下代码.

MyEventHandler handler = null; //Declare the handler

foreach (string pname in group)
{
  handler = getHandler(pname); //Get the handler
  if(handler == null)
  {                        
      throw new KeyNotFoundException("No user " + pname + " could be found");
  }
  //invoke the handler
  handler.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
}
Run Code Online (Sandbox Code Playgroud)

所以我得到了处理程序和调用BeginInvoke方法.但是在BeginInvoke被调用之前它会进入下一次迭代并且处理程序值会发生变化.因此BeginInvoke,这个新的处理程序正在参与其中.

希望你明白我的观点.那我怎么能消除这个问题呢?BeginInvoke因为我觉得这是一个时间的流逝,我不想打电话给睡觉.

有任何想法吗?

Update1 我很确定在调用BeginInvoke()之前处理程序对象会被更改.我猜BeginInvoke需要一些时间来创建一个单独的线程来调用另一个函数.

UPDATE2 此代码位于WCF服务中,客户端调用一个函数,该函数依次使用此函数.我为每个客户端分别存储在我的服务器中的处理程序.WCF服务具有双工合同,为客户端分隔会话.我看到执行此函数后,同一个用户被调用两次.但我设置了一个断点并调试它(这给BeginInvoke提供了调用函数所需的时间)它"完美地"工作.我非常确定我在线程中也遇到了这个问题,我在循环中创建了多个线程.如果线程委托具有参数a,b,c,并且如果在下一次迭代开始时更改它,则会发生相同的行为.我之前有多少人遇到过这个问题.如果我放一个Sleep()或者如果我复制一个处理程序并使用copy调用它就可以了.

UPDATE3

好的,我现在已经测试过了.我刚刚添加了Thread.Sleep(),如下所示.

chatTo.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
Thread.Sleep(500);
Run Code Online (Sandbox Code Playgroud)

它的工作就像一个魅力.有什么想法吗?

更新4

我创建了一个演示问题的线程示例,我已将其上传到此处.我希望解决这个问题也能解决我的问题.请检查样品.

ang*_*son 5

好的,在你的第四次编辑后,你提供了一个例子,它表明了一个问题,当然,但不是你要求帮助的问题.

你在问题中说的是:

  • 我在委托变量上使用BeginInvoke,然后更改变量,并以某种方式调用我的委托两次

您在发布的代码中展示的是:

  • 我在匿名方法中捕获循环变量,并以某种方式使用错误的变量值

这些都不是同样的问题!

你发布的代码行为不端的原因是所讨论的代码实际上看起来像这样:

int i;
for (i = 0; i < 10; i++)
    ... create delegate, capture i, spawn thread
Run Code Online (Sandbox Code Playgroud)

在这里,您将为所有线程捕获相同的变量.如果一个线程在循环更改变量之前没有开始执行,那么是的,您将看到该变量的"不正确的值".

但是,如果您更改这样的代码:

for (int i = 0; i < 10; i++)
{
    int j = i;
    ThreadStart threadStartObj = new ThreadStart(
        delegate { PrintValueThreadFunction(j, j); });
                                            ^
                                            |
                                            +-- use j instead of i here
Run Code Online (Sandbox Code Playgroud)

然后,您将为每个线程捕获一个"新"变量,该变量不会被更改.

所以,问题仍然存在.这是你遇到的问题吗?如果是这样,那么下次羞辱你,不要简化问题.你在浪费人们的时间,尤其是你自己的时间.如果您在上面发布了类似上面的代码,那么您将在几分钟内得到一个答案(或一个重复的问题,指向现有的答案,有很多).

如果这不是您遇到的问题,那么您仍然遇到一个事件处理程序的问题,就像在不止一次调用的原始代码中一样,返回并生成一个更好的示例项目.