使用 lock 取代 MethodImplOptions.Synchronized

情境:

ASP.NET 的網站忽然某一個功能會出現 System.Threading.SynchronizationLockException 其它都是正常.

錯誤訊息:

System.Threading.SynchronizationLockException: Object synchronization method was called from an unsynchronized block of code.

測試:

測試發現如果使用MethodImplOptions.Synchronized,若thread進入執行並故意abort掉,可以重現.SynchronizationLockException。

若改用lock則不會發生問題

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Runtime.CompilerServices;

using System.Text;

using System.Windows.Forms;

using System.Threading;

 

namespace LockDemo

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e)

        {           

            Thread t1 = new Thread(MyLib.Run);

            t1.Start();

 

            Thread t2 = new Thread(MyLib.Run2);

            t2.Start();

 

            Thread t3 = new Thread(MyLib.Run3);

            t3.Start();

 

            Thread t4 = new Thread(MyLib.Run4);

            t4.Start();

        }

    }

 

    public class MyLib

    {

        public static int intCount = 0;

 

        [MethodImpl(MethodImplOptions.Synchronized)]

        public static void Run()

        {

            System.Threading.Thread.Sleep(5000);

            intCount++;

 

            MessageBox.Show(String.Format("RUN1:Thread ID {0}:{1}",

                System.Threading.Thread.CurrentThread.ManagedThreadId.ToString(),

                MyLib.intCount.ToString()

                ));

        }

 

        [MethodImpl(MethodImplOptions.Synchronized)]

        public static void Run2()

        {

            System.Threading.Thread.Sleep(5000);

            intCount++;

 

            MessageBox.Show(String.Format("RUN2:Thread ID {0}:{1}",

                System.Threading.Thread.CurrentThread.ManagedThreadId.ToString(),

                MyLib.intCount.ToString()

                ));

        }

 

 

        public static void Run3()

        {

            System.Threading.Thread.Sleep(5000);

            intCount++;

 

            MessageBox.Show(String.Format("RUN3:Thread ID {0}:{1}",

                System.Threading.Thread.CurrentThread.ManagedThreadId.ToString(),

                MyLib.intCount.ToString()

                ));

        }

 

        public static void Run4()

        {

            System.Threading.Thread.Sleep(5000);

            intCount++;

 

            MessageBox.Show(String.Format("RUN4:Thread ID {0}:{1}",

                System.Threading.Thread.CurrentThread.ManagedThreadId.ToString(),

                MyLib.intCount.ToString()

                ));

        }

    }

}

 

Enjoy. Jacky