为什么突然一个线程运行一个方法的一部分?

时间:2013-02-19 09:48:45

标签: c# .net multithreading thread-safety

我真的被困在某个地方,这个地方是我唯一能得到答案的地方。我求你从头到尾阅读它。

我有一个方法,如下所示:

public void Execute(Data data)
{
    bool IsOk = false;
    //1st point
    IsOk = Check1();

    //2nd point
    if(IsOk)
      IsOk = Check2();

    //3nd point
    if(IsOk)
      IsOk = Check3();

    //4th point
    if(IsOk)
       SendMessage();

}

数据对象是通过STATIC方法获取的,以防止超过1个线程访问它,如下所示:

[MethodImpl(MethodImplOptions.Synchronized)]
public static DataCollection GetDataColl()
{
   //By syncronizing, I'm guaranteeing every data is unique.
   DataCollection Result = new DataCollection();
   Result = GetDataFromDatabase();//Changing status in order to prevent getting it again
   return Result;
}

在此之后,我将以下方法提供给THREADS来处理DataCollection

//When invoked, creates the threads that runs my actual processing method
private void btnStart_Click(object sender, EventArgs e)
{
   for(int i= 1; i <= 2; i++ )
   {
      Thread ProcessThread = new Thread(ProcessData);
      ProcessThread.Start();
   }
}

//Process the data
private void ProcessData()
{
   DataCollection Coll = GetDataColl(); //GetDataColl is static, threadsafe that can be invoked only by 1 thread at a time method.

   //Foreach through data and execute the PROBLEMATIC method "Execute" at the beginning
   foreach(Data dta in Coll)
      Execute(dta); //The problem occurs in this method
}

问题时有发生,并非总是如此,但你可以给它约20%的时间,这比我想象的还要多。以下是发生的事情:

  1. Thread 1:运行执行方法的第一点
  2. Thread 1:运行Execute方法的第二点
  3. Thread 1:运行执行方法的第3点
  4. Thread 2:运行Execute方法的第4点 - &gt;奇怪!
  5. Thread 1:运行Execute方法的第4点
  6. 出乎意料的是,在方法的中间中,这个新线程在这个点处正确,并执行整个方法的一部分。这个新帖子(Thread 2)确实 NOT 甚至可以进入第1,第2和第3点。

    有时也会按此顺序发生:

    1. Thread 1:运行执行方法的第一点
    2. Thread 1:运行Execute方法的第二点
    3. Thread 2:运行Execute方法的第4点 - &gt;奇怪!
    4. Thread 1:运行Execute方法的第3点。
    5. Thread 1:运行Execute方法的第4点。
    6. 所有这些都是从日志文件中读取和写入的,而不是通过调试。当我进行调试时,一切似乎都很好。

      我使用了log4net,以下是发生的事情的简化示例:

      2013-02-19 09:53:02,057 [39] DataId: 4356502 - Check1
      2013-02-19 09:53:02,088 [39] DataId: 4356502 - Check2
      2013-02-19 09:53:02,088 [39] DataId: 4356502 - Check3
      2013-02-19 09:53:02,542 [39] DataId: 4356502 - Send
      2013-02-19 09:53:02,573 [46] DataId: 4356502 - Send
      

      线程No 46甚至没有进入Check 1,2,3。

2 个答案:

答案 0 :(得分:0)

我已经尝试过您的代码,虽然稍有改动,但似乎工作正常。检查输出的高位,确保线程[46]在被保持之前没有在线程[39]之前执行。

th1 - Check 1 example string 235236
th1 - Check 2 example string 235236 <- thread1 gets to #2 and stops
th2 - Check 1 example string 235236
th2 - Check 2 example string 235236
th2 - Check 3 example string 235236 <- thread2 gets to #3
th1 - Check 3 example string 235236 <- thread1 starts up again, at #3
th2 - Check 4 example string 235236 <- thread4 then finishes off with #4
th2 - Check 1 example string 135236
th2 - Check 2 example string 135236
th2 - Check 3 example string 135236
th1 - Check 4 example string 235236 <- thread1 appears and finishes #4
th2 - Check 4 example string 135236

答案 1 :(得分:0)

我在这里解决了这个问题,

当主线程启动时,它使用一个保存单例Message Collection的STATIC变量。因为,其他线程试图在这个单例集合上运行,主线程暂时改变了值(这显然是我的错误,我通过克隆更新的对象解决了它)并导致其他线程使用这个修改过的对象,当它们应该具有原始值时

这种情况看起来像是一个我问过的问题。

非常感谢您的帮助。