导航

MethodImpl同步方法

Posted on 2006-09-15 10:04  hcfalan  阅读(5039)  评论(1编辑  收藏  举报

同步方法

     多线程开发的时候,开发者经常会遇到在一个方法里锁定和释放一个对象的情景,本文演示了如何使用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(3232);
        
this.m_CreateThreads.Name = "CreateThreads";
        
this.m_CreateThreads.Size = new System.Drawing.Size(11223);
        
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(3280);
        
this.m_CounterLabel.Name = "m_CounterLabel";
        
this.m_CounterLabel.Size = new System.Drawing.Size(12864);
        
this.m_CounterLabel.TabIndex = 1;
        
this.m_CounterLabel.Text = "0";
        
        
this.ClientSize = new System.Drawing.Size(248165);
        
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