.net 可能的线程、变量复制问题

.net 可能的线程、变量复制问题,.net,multithreading,.net,Multithreading,我们有一个运行如下例程的应用程序: protected string _largeFile; Execute() //this executes in basically an infinite loop. { _largeFile = ""; DoStuff(); DoStuff(); _largeFile = "ReallyBigString"; //sometimes 4-5Mb if(_largeFile != "") {

我们有一个运行如下例程的应用程序:

protected string _largeFile;

Execute()   //this executes in basically an infinite loop.
{
    _largeFile = "";
    DoStuff();
    DoStuff();
    _largeFile = "ReallyBigString"; //sometimes 4-5Mb
      if(_largeFile != "")
      {
       RaiseEvent();
      }
    DoStuff();
    DoSTuff();
    Thread.Sleep(5000);  //wait 5 seconds;
//repeat
}

CatchEvent()
{
     SendLargeFileToWebService(_largeFile);
}
此代码在我们无法控制的客户端PC上执行。代码基本上得到一个大文件并将其发送回服务器。问题是,有时返回给web服务的大文件是空的。我们对此进行了一段时间的研究,但无法确定这是如何发生的

唯一有价值的解决方案是,引发事件所需的时间太长,以至于当Execute方法执行后续时间时,在SendLargeFileToWebService能够执行此操作之前,类级别的_largeFile变量被清除


我的问题是:这可能吗?编写代码的开发人员辩称,使用类级别变量的原因是为了避免复制实例变量并将其传递给新线程(可能是执行事件的线程)。这似乎是正确的方法吗?对于这一点,可能没有银弹答案,所以如果有人能在引发事件时向我解释一些标准,例如事件参数vs.类变量,我将不胜感激。我也很好奇这个提议是否合理。是他们在评估来自不同线程的大字符串时的已知问题。

我对这个场景有点不清楚。但是从您的描述来看,Execute方法似乎是从多个线程调用的。如果是这样,那么您肯定有一个bug,因为如果在任何时候运行两个Execute方法,您将在
\u largeFile
上有一个争用条件

有两种方法可以解决此问题

  • \u largeFile
    的内容作为参数传递以执行
  • 在execute方法中添加一个锁,以防止多个线程同时执行它
    他们不想传递变量的论点有点懒惰和IMHO的味道,不应被视为有效论点

    我对这个场景有点不清楚。但是从您的描述来看,Execute方法似乎是从多个线程调用的。如果是这样,那么您肯定有一个bug,因为如果在任何时候运行两个Execute方法,您将在
    \u largeFile
    上有一个争用条件

    有两种方法可以解决此问题

  • \u largeFile
    的内容作为参数传递以执行
  • 在execute方法中添加一个锁,以防止多个线程同时执行它
    他们不想传递变量的论点有点懒惰和IMHO的味道,不应被视为有效论点

    所以,执行清除大文件,做一些事情,也许重新加载大文件。 如果重新加载,它会通知另一个线程。 然后,另一个线程会花一些时间通过web或其他方式发送较大的文件。 同时,Execute可以做一些其他事情,然后等待5秒钟,然后重复

    对吗

    如果是这样,那么在发送之前,_largeFile可能会被清除(回到Execute的顶部)。但是,有一些但是:

  • 我假设SendLargeFileTowerService(_largeFile);复制_largeFile的值(即复制指针的值,不复制所有内容)? 如果是这样,那么您是说在SendLarge之前清除了_largeFile。。。甚至开始。 考虑到Execute做了一些事情,然后等待5秒钟,这看起来确实很奇怪。但是等一下,也许是大的。。。正在忙于发送一个旧文件,所以当它到达下一个文件时,它错过了机会?接球真的成了一个圈,对吗

    
    永远
    {
    而(!没什么可抓的)
    等待();
    //哦,抓住什么了
    CatchEvent();//调用SendLarge…这可能需要一些时间
    }//重复
    

  • 因此,当CatchEvent来检查另一个事件时,\u largeFile已经重置

    或者每个CatchEvent()都发生在一个新线程中?我对此表示怀疑

  • 我记不起其他的“但是”,因为我认为以上就是问题所在,尽管我对.NET不太了解,等等
  • 无论如何,试试看 -增加睡眠()时间(只是一个测试,而不是一个解决方案!) -在大文件周围放置一个锁(同样,作为测试)或传递它

    还有,检查一下——在大量大文件“背靠背”发送后,是否会发生这种情况?这可能意味着我的#1场景——即发送线程落后太多,最终落后超过5秒,并丢失文件。理论上,它也可以跳过一个文件,转到下一个文件。那会发生吗

    最后,我读了你的问题很多次,甚至在我觉得我可能理解你试图描述的东西之前——就像另一个答案一样,我发现它不清楚。
    因此,如果我对这个问题猜错了,那么,嘿,我可能也猜错了答案。

    所以,执行清除大文件,做一些事情,可能重新加载大文件。 如果重新加载,它会通知另一个线程。 然后,另一个线程会花一些时间通过web或其他方式发送较大的文件。 同时,Execute可以做一些其他事情,然后等待5秒钟,然后重复

    对吗

    如果是这样,那么在发送之前,_largeFile可能会被清除(回到Execute的顶部)。但是,有一些但是:

  • 我假设SendLargeFileTowerService(_largeFile);复制_largeFile的值(即复制指针的值,不复制所有内容)? 如果是这样,那么您是说在SendLarge之前清除了_largeFile。。。甚至开始。 考虑到Execute做了一些事情,然后等待5秒钟,这看起来确实很奇怪。但是等一下,也许是大的。。。正在忙于发送一个旧文件,所以当它到达下一个文件时,它错过了机会?接球真的成了一个圈,对吗

    
    永远
    {
    而(!没什么可抓的)
    等待();
    //哦,抓住什么了
    CatchEvent();//调用SendLarge…这可能需要一些时间
    }//重复
    

  • 所以到了Catch的时候 for_ever() { while (!nothing_to_catch) Wait(); // !oh, caught something CatchEvent(); // calls SendLarge... which could take a while } // repeat