为什么微软这个样本code崩溃? [英] Why does this sample code from Microsoft crash?

查看:115
本文介绍了为什么微软这个样本code崩溃?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想学习一些关于多线程在.NET和一把抓起的 MSDN 。它编译罚款,但崩溃在运行时。我希望微软会告诉我正确的方式来创建多个线程。我想不通为什么它会崩溃,但。有人可以帮忙吗?

  // Mutex.cs
//互斥对象的实例
使用系统;
使用的System.Threading;

公共类MutexSample
{
   静态互斥GM1;
   静态互斥GM2;
   const int的ITERS = 100;
   静态的AutoResetEvent事件1 =新的AutoResetEvent(假);
   静态的AutoResetEvent EVENT2 =新的AutoResetEvent(假);
   静态的AutoResetEvent EVENT3 =新的AutoResetEvent(假);
   静态的AutoResetEvent Event4 =新的AutoResetEvent(假);

   公共静态无效的主要(字串[] args)
   {
      Console.WriteLine(互斥样本...);

      //创建互斥initialOwned,以MyMutex的名字。
      GM1 =新的互斥(真的,MyMutex);
      //创建互斥initialOwned,没有名字。
      GM2 =新的mutex(真正的);

      Console.WriteLine( - 主营旗下拥有GM1和GM2);

      的AutoResetEvent [] EVS =新的AutoResetEvent [4];
      EVS [0] =事件1; //事件的T1
      EVS [1] = EVENT2; //事件T2
      EVS [2] = EVENT3; //事件T3
      EVS [3] = Event4; //事件T4

      MutexSample TM =新MutexSample();
      线T1 =新主题(新的ThreadStart(tm.t1Start));
      线程T2 =新主题(新的ThreadStart(tm.t2Start));
      螺纹T3 =新主题(新的ThreadStart(tm.t3Start));
      螺纹T4 =新主题(新的ThreadStart(tm.t4Start));

      t1.Start(); //是否([] GM1和GM2的互斥)Mutex.WaitAll
      t2.Start(); //是否Mutex.WaitOne(互斥GM1)
      t3.Start(); //是否([] GM1和GM2的互斥)Mutex.WaitAny
      t4.Start(); //是否Mutex.WaitOne(互斥GM2)

      Thread.sleep代码(2000);
      Console.WriteLine( - 主要排放GM1);
      gM1.ReleaseMutex(); // t2和t3将结束,信号

      Thread.sleep代码(1000);
      Console.WriteLine( - 主要排放GM2);
      gM2.ReleaseMutex(); // T1和T4将结束,信号

      //等待,直到所有四个线程发出信号,他们正在做的。
      WaitHandle.WaitAll的(EVS);
      Console.WriteLine(...互斥样本);
   }

   公共无效t1Start()
   {
      Console.WriteLine(t1Start开始,Mutex.WaitAll(互斥[]));
      互斥[] GMS =新的mutex [2] {GM1,GM2};
      Mutex.WaitAll(GMS); //等待,直到GM1和GM2被释放
      Thread.sleep代码(2000);
      Console.WriteLine(t1Start完成,Mutex.WaitAll(互斥[])满意);
      Event1.Set(); // AutoResetEvent.Set()萎靡不振方法完成
   }

   公共无效t2Start()
   {
      Console.WriteLine(t2Start开始,gM1.WaitOne());
      gM1.WaitOne(); //等待,直到互斥GM1被释放
      Console.WriteLine(t2Start完成,gM1.WaitOne()满意);
      Event2.Set(); // AutoResetEvent.Set()萎靡不振方法完成
   }

   公共无效t3Start()
   {
      Console.WriteLine(t3Start开始,Mutex.WaitAny(互斥[]));
      互斥[] GMS =新的mutex [2] {GM1,GM2};
      Mutex.WaitAny(GMS); //等待直到互斥被释放
      Console.WriteLine(t3Start完成,Mutex.WaitAny(互斥[]));
      Event3.Set(); // AutoResetEvent.Set()萎靡不振方法完成
   }

   公共无效t4Start()
   {
      Console.WriteLine(t4Start开始,gM2.WaitOne());
      gM2.WaitOne(); //等待,直到互斥GM2被释放
      Console.WriteLine(t4Start完成,gM2.WaitOne());
      Event4.Set(); // AutoResetEvent.Set()萎靡不振方法完成
   }
}
 

解决方案

您正在关注从VS2003 / .NET 1.1时代的教程。

AbandonedMutexException 是在.NET 2推出,因此为什么样code现在失败了,如果用在.NET 2或更高版本。

每个线程(通过等待功能)中获得的有关互斥应在线程退出之前被释放。在1.1 code,如果一个线程退出,同时拥有一个互斥体,下一个等待线程获得互斥仿佛什么不幸发生。然而,由于这种经常导致不正确的行为(例如,一个线程退出而更新状态由互斥保护),一个变化到BCL制成

说实话,写互斥基于code是很少,如果有的话,你想要做最真实的一句话线程的情景是什么。如果这仅仅是一个学习锻炼,我建议忽略它们。如果你试图解决一个现实世界的情况下,你认为互斥体可能是解决办法,我建议你问包含的细节一个单独的问题。


重新编写的4线程函数退出之前释放适当的互斥。唯一真正棘手的是T3(这是获得互斥工作了):

 公共无效t1Start()
{
    Console.WriteLine(t1Start开始,Mutex.WaitAll(互斥[]));
    互斥[] GMS =新的mutex [2] {GM1,GM2};
    Mutex.WaitAll(GMS); //等待,直到GM1和GM2被释放
    Thread.sleep代码(2000);
    Console.WriteLine(t1Start完成,Mutex.WaitAll(互斥[])满意);
    Event1.Set(); // AutoResetEvent.Set()萎靡不振方法完成
    gM1.ReleaseMutex();
    gM2.ReleaseMutex();
}

公共无效t2Start()
{
    Console.WriteLine(t2Start开始,gM1.WaitOne());
    gM1.WaitOne(); //等待,直到互斥GM1被释放
    Console.WriteLine(t2Start完成,gM1.WaitOne()满意);
    Event2.Set(); // AutoResetEvent.Set()萎靡不振方法完成
    gM1.ReleaseMutex();
}

公共无效t3Start()
{
    Console.WriteLine(t3Start开始,Mutex.WaitAny(互斥[]));
    互斥[] GMS =新的mutex [2] {GM1,GM2};
    INT mxObtained = Mutex.WaitAny(GMS); //等待直到互斥被释放
    Console.WriteLine(t3Start完成,Mutex.WaitAny(互斥[]));
    Event3.Set(); // AutoResetEvent.Set()萎靡不振方法完成
    GMS [mxObtained] .ReleaseMutex();
}

公共无效t4Start()
{
    Console.WriteLine(t4Start开始,gM2.WaitOne());
    gM2.WaitOne(); //等待,直到互斥GM2被释放
    Console.WriteLine(t4Start完成,gM2.WaitOne());
    Event4.Set(); // AutoResetEvent.Set()萎靡不振方法完成
    gM2.ReleaseMutex();
}
 

I wanted to learn a little about multi threading in .NET and grabbed this sample from MSDN. It compiles fine but crashes at runtime. I was hoping Microsoft would have told me the right way to create multiple threads. I can't work out why it crashes though. Can someone help?

// Mutex.cs
// Mutex object example
using System;
using System.Threading;

public class MutexSample
{
   static Mutex gM1;
   static Mutex gM2;
   const int ITERS = 100;
   static AutoResetEvent Event1 = new AutoResetEvent(false);
   static AutoResetEvent Event2 = new AutoResetEvent(false);
   static AutoResetEvent Event3 = new AutoResetEvent(false);
   static AutoResetEvent Event4 = new AutoResetEvent(false);

   public static void Main(String[] args)
   {
      Console.WriteLine("Mutex Sample ...");

      // Create Mutex initialOwned, with name of "MyMutex".
      gM1 = new Mutex(true,"MyMutex");
      // Create Mutex initialOwned, with no name.
      gM2 = new Mutex(true);

      Console.WriteLine(" - Main Owns gM1 and gM2");

      AutoResetEvent[] evs = new AutoResetEvent[4];
      evs[0] = Event1;    // Event for t1
      evs[1] = Event2;    // Event for t2
      evs[2] = Event3;    // Event for t3
      evs[3] = Event4;    // Event for t4

      MutexSample tm = new MutexSample( );
      Thread t1 = new Thread(new ThreadStart(tm.t1Start));
      Thread t2 = new Thread(new ThreadStart(tm.t2Start));
      Thread t3 = new Thread(new ThreadStart(tm.t3Start));
      Thread t4 = new Thread(new ThreadStart(tm.t4Start));

      t1.Start( );   // Does Mutex.WaitAll(Mutex[] of gM1 and gM2)
      t2.Start( );   // Does Mutex.WaitOne(Mutex gM1)
      t3.Start( );   // Does Mutex.WaitAny(Mutex[] of gM1 and gM2)
      t4.Start( );   // Does Mutex.WaitOne(Mutex gM2)

      Thread.Sleep(2000);
      Console.WriteLine(" - Main releases gM1");
      gM1.ReleaseMutex( );  // t2 and t3 will end and signal

      Thread.Sleep(1000);
      Console.WriteLine(" - Main releases gM2");
      gM2.ReleaseMutex( );  // t1 and t4 will end and signal

      // Waiting until all four threads signal that they are done.
      WaitHandle.WaitAll(evs); 
      Console.WriteLine("... Mutex Sample");
   }

   public void t1Start( )
   {
      Console.WriteLine("t1Start started,  Mutex.WaitAll(Mutex[])");
      Mutex[] gMs = new Mutex[2] { gM1, gM2};
      Mutex.WaitAll(gMs);  // Waits until both gM1 and gM2 are released
      Thread.Sleep(2000);
      Console.WriteLine("t1Start finished, Mutex.WaitAll(Mutex[]) satisfied");
      Event1.Set( );      // AutoResetEvent.Set() flagging method is done
   }

   public void t2Start( )
   {
      Console.WriteLine("t2Start started,  gM1.WaitOne( )");
      gM1.WaitOne( );    // Waits until Mutex gM1 is released
      Console.WriteLine("t2Start finished, gM1.WaitOne( ) satisfied");
      Event2.Set( );     // AutoResetEvent.Set() flagging method is done
   }

   public void t3Start( )
   {
      Console.WriteLine("t3Start started,  Mutex.WaitAny(Mutex[])");
      Mutex[] gMs = new Mutex[2] { gM1, gM2};
      Mutex.WaitAny(gMs);  // Waits until either Mutex is released
      Console.WriteLine("t3Start finished, Mutex.WaitAny(Mutex[])");
      Event3.Set( );       // AutoResetEvent.Set() flagging method is done
   }

   public void t4Start( )
   {
      Console.WriteLine("t4Start started,  gM2.WaitOne( )");
      gM2.WaitOne( );   // Waits until Mutex gM2 is released
      Console.WriteLine("t4Start finished, gM2.WaitOne( )");
      Event4.Set( );    // AutoResetEvent.Set() flagging method is done
   }
}

解决方案

You're following a tutorial from the VS2003/.NET 1.1 era.

AbandonedMutexException was introduced in .NET 2, hence why the sample code now fails, if used on .NET 2 or later.

The appropriate mutexes obtained by each thread (through Wait functions) should be released before the threads exit. In 1.1 code, if a thread exits whilst owning a mutex, the next waiting thread obtains the mutex as if nothing untoward has happened. However, since this frequently leads to incorrect behaviour (e.g. a thread exited whilst updating state protected by the mutex), a change was made to the BCL.

To be honest, writing Mutex based code is rarely, if ever, what you want to do for most real word threading scenarios. If this is just a learning exercise, I'd suggest ignoring them. If you're trying to solve a real-world scenario, and you thought mutexes might be the solution, I'd suggest you ask a separate question containing the details.


Re-written the 4 thread functions to release the appropriate mutexes before exit. The only really tricky one was t3 (working out which mutex was obtained):

public void t1Start()
{
    Console.WriteLine("t1Start started,  Mutex.WaitAll(Mutex[])");
    Mutex[] gMs = new Mutex[2] { gM1, gM2 };
    Mutex.WaitAll(gMs);  // Waits until both gM1 and gM2 are released
    Thread.Sleep(2000);
    Console.WriteLine("t1Start finished, Mutex.WaitAll(Mutex[]) satisfied");
    Event1.Set();      // AutoResetEvent.Set() flagging method is done
    gM1.ReleaseMutex();
    gM2.ReleaseMutex();
}

public void t2Start()
{
    Console.WriteLine("t2Start started,  gM1.WaitOne( )");
    gM1.WaitOne();    // Waits until Mutex gM1 is released
    Console.WriteLine("t2Start finished, gM1.WaitOne( ) satisfied");
    Event2.Set();     // AutoResetEvent.Set() flagging method is done
    gM1.ReleaseMutex();
}

public void t3Start()
{
    Console.WriteLine("t3Start started,  Mutex.WaitAny(Mutex[])");
    Mutex[] gMs = new Mutex[2] { gM1, gM2 };
    int mxObtained = Mutex.WaitAny(gMs);  // Waits until either Mutex is released
    Console.WriteLine("t3Start finished, Mutex.WaitAny(Mutex[])");
    Event3.Set();       // AutoResetEvent.Set() flagging method is done
    gMs[mxObtained].ReleaseMutex();
}

public void t4Start()
{
    Console.WriteLine("t4Start started,  gM2.WaitOne( )");
    gM2.WaitOne();   // Waits until Mutex gM2 is released
    Console.WriteLine("t4Start finished, gM2.WaitOne( )");
    Event4.Set();    // AutoResetEvent.Set() flagging method is done
    gM2.ReleaseMutex();
}

这篇关于为什么微软这个样本code崩溃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆