可能的线程,可变副本问题

时间:2010-01-16 17:22:43

标签: .net multithreading

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

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服务的largeFile是空白的。我们已经研究了一段时间,但无法确定这是如何发生的。

唯一似乎有任何优点的解决方案是,RaiseTheEvent花费的时间太长,以至于当Execute方法执行后续时间时,类级_largeFile变量在SendLargeFileToWebService能够执行此操作之前被清除

我的问题:这是否合情合理?编写代码的开发人员保护类级别变量的原因是避免必须复制实例变量并将其传递给新线程(可能是事件执行的线程)。这看起来是正确的方法吗?可能没有灵丹妙药的答案,所以如果有人能够向我解释一些标准的事件 - 事件争论与类变量在举起事件时我会很感激。如果拟议的问题甚至可能合理,我也很好奇。在评估来自不同线程的大字符串时,他们是否知道问题。

2 个答案:

答案 0 :(得分:4)

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

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

  1. _largeFile的内容作为参数传递给执行
  2. 在execute方法中添加一个锁,以防止多个线程同时执行它。
  3. 他们不想将变量传递给懒惰和恕我直言的论点不应被视为有效的论据。

答案 1 :(得分:1)

所以,执行清除_largeFile,做一些事情,可能会重新加载_largeFile。 如果重新加载,它会通知另一个线程。 然后其他线程花费一些时间在网络上发送_largeFile或其他东西。 同时,Execute可以做其他一些事情,然后等待5秒,然后重复。

这是对的吗?

如果是这样,那么可能在发送之前_largeFile被清除(返回执行顶部)。但是,还有一些问题:

  1. 我假设SendLargeFileToWebService(_largeFile); 拷贝 _largeFile的值(即复制指针的值,不复制所有内容)? 如果是这样,那么你说_LaggeFile在SendLarge之前被清除......甚至启动。 鉴于Execute做了一些事情,然后等了5秒,这看起来很奇怪。但是等一下,也许SendLarge ......正在忙着发送一个旧文件,所以当它到达下一个文件时,它已经错过了它的机会?即Catch真的在一个循环中吗?:

    for_ever()
    {
        while (!nothing_to_catch)
            Wait();
        // !oh, caught something
        CatchEvent(); // calls SendLarge... which could take a while
    } // repeat
    

  2. 所以当CatchEvent来检查另一个事件时,_largeFile已被重置。

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

    1. 我记不起其他'但是'因为我觉得上面是问题所在,即使我不熟悉.NET等等。
    2. 无论如何,试试吧 - 增加睡眠时间(仅作为测试 - 而不是解决方案!) - 在_largeFile周围设置锁定(再次,作为测试)或传递

      而且,检查 - 是否会在“背靠背”发送大量文件之后发生?这表明我的#1场景 - 即发送线程远远落后于它最终落后超过5秒,并丢失了文件。从理论上讲,它也可以跳过文件并转到下一个文件。那会发生吗?

      最后,在我甚至觉得我可能了解你想要描述的内容之前,我多次读过你的问题 - 就像另一个答案一样,我发现它不清楚。 所以,如果我猜错了这个问题,那么,嘿,我可能也猜错了答案。