MethodImpl同步方法

来源:互联网 发布:淘宝一分钱秒杀验证 编辑:程序博客网 时间:2024/06/06 06:31

同步方法

     多线程开发的时候,开发者经常会遇到在一个方法里锁定和释放一个对象的情景,本文演示了如何使用MethodImpl属性标识一个需要同步的方法,让编译器自动产生同步代码。

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

public class MyClass
{        
    [System.Runtime.CompilerServices.MethodImpl(
        System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
    public void SetCounter(int counter)
    {
        this.Counter = counter;
    }

    
    [System.Runtime.CompilerServices.MethodImpl(
        System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
    public int GetCounter()
    {
        return this.Counter;
    }

    
    protected string m_CountingString;
    protected int Counter
    {
        set
        {
            m_CountingString = "";
            m_CountingString = value.ToString();
        }

        get
        {
            return Convert.ToInt32(m_CountingString);
        }

    }

    
    public MyClass()
    {
        m_CountingString = "0";
    }

}


public class MyForm : System.Windows.Forms.Form
{
    public static void Main()
    {
        try
        {
        Application.Run(new MyForm());
        }

        catch(Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Console.ReadLine();
        }

    }


    private Button m_CreateThreads;
    private Label m_CounterLabel;
    protected MyClass m_MyClass;
    
    public MyForm()
    {
        this.m_CreateThreads = new System.Windows.Forms.Button();
        this.m_CreateThreads.Location = new System.Drawing.Point(32, 32);
        this.m_CreateThreads.Name = "CreateThreads";
        this.m_CreateThreads.Size = new System.Drawing.Size(112, 23);
        this.m_CreateThreads.TabIndex = 0;
        this.m_CreateThreads.Text = "Create Threads";        
        this.m_CreateThreads.Click += new System.EventHandler(this.OnCreateThreads);
        
        this.m_CounterLabel = new System.Windows.Forms.Label();
        this.m_CounterLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 24F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
        this.m_CounterLabel.ForeColor = System.Drawing.Color.Red;
        this.m_CounterLabel.Location = new System.Drawing.Point(32, 80);
        this.m_CounterLabel.Name = "m_CounterLabel";
        this.m_CounterLabel.Size = new System.Drawing.Size(128, 64);
        this.m_CounterLabel.TabIndex = 1;
        this.m_CounterLabel.Text = "0";
        
        this.ClientSize = new System.Drawing.Size(248, 165);
        this.Controls.AddRange(new System.Windows.Forms.Control[] 
            {
                this.m_CreateThreads,
                this.m_CounterLabel
            }
);
        this.Text = "SynchMethod";
         
        m_MyClass = new MyClass();
        m_CounterLabel.Text = m_MyClass.GetCounter().ToString();
    }

    
    private void OnCreateThreads(object sender,EventArgs e)
    {
        ThreadStart threadStart1 = new ThreadStart(IncrementCounter);
        Thread thread1 = new Thread(threadStart1);
        thread1.IsBackground = true;
        thread1.Start();
        
        ThreadStart threadStart2 = new ThreadStart(UpdateCounter);
        Thread thread2 = new Thread(threadStart2);
        thread2.IsBackground = true;
        thread2.Start();
    }

    
    private void ChangeLabel()
    {
        if (InvokeRequired)
        {
            this.Invoke(new MethodInvoker(ChangeLabel));
            return;
        }

        this.m_CounterLabel.Text = m_MyClass.GetCounter().ToString();
    }

    
    protected void IncrementCounter()
    {
        while(true)
        {
            int counter = m_MyClass.GetCounter();
            counter++;
            Console.WriteLine("IncrementCounter:{0}", counter);
            m_MyClass.SetCounter(counter);
            Thread.Sleep(300);
        }

    }

    
    protected void UpdateCounter()
    {
        while(true)
        {
            Console.WriteLine("UpdateCounter");
            this.ChangeLabel();
            Thread.Sleep(300);
        }

    }

}

我们使用ildasm看看编译器对MyClass.GetCounter方法产生的代码:

.method public hidebysig instance int32  GetCounter() cil managed synchronized
{
  // 代码大小       12 (0xc)
  .maxstack  1
  .locals init ([0] int32 CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  call       instance int32 MyClass::get_Counter()
  IL_0007:  stloc.0
  IL_0008:  br.s       IL_000a
  IL_000a:  ldloc.0
  IL_000b:  ret
// end of method MyClass::GetCounter
0 0
原创粉丝点击