BufferedGraphics BufferedGraphics BufferedGraphics BufferedGraphics Class

定義

ダブル バッファリングのためのグラフィックス バッファーを提供します。Provides a graphics buffer for double buffering.

public ref class BufferedGraphics sealed : IDisposable
public sealed class BufferedGraphics : IDisposable
type BufferedGraphics = class
    interface IDisposable
Public NotInheritable Class BufferedGraphics
Implements IDisposable
継承
BufferedGraphicsBufferedGraphicsBufferedGraphicsBufferedGraphics
実装

次のコード例に示しますを使用して、BufferedGraphics実装のバッファリングのいくつかの型を使用してグラフィックスを描画するオブジェクト。The following code example demonstrates using a BufferedGraphics object to draw graphics using several types of buffering implementations. フォームをクリックしてまたは起動をエラーの原因が更新プログラムを描画するタイマーを停止します。Clicking the form alternately starts and stops a timer that causes draw updates. 描画の更新を使用すると、ダブル バッファリングの効果を確認できます。The draw updates allow you to observe the effect of double buffering. フォームを順番に次の描画モードを右クリックします。Right-clicking the form cycles through the following drawing modes:

各モードでは、現在のモードを識別し、各マウス ボタンが押されたときに発生する動作について説明テキストを描画します。In each mode, text is drawn that identifies the current mode and describes the behavior that occurs when each mouse button is pressed.

#using <System.Windows.Forms.dll>
#using <System.Drawing.dll>
#using <System.dll>

using namespace System;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Windows::Forms;

namespace BufferingExample
{
   public ref class BufferingExample: public Form
   {
   private:
      BufferedGraphicsContext^ context;
      BufferedGraphics^ grafx;
      Byte bufferingMode;
      array<String^>^bufferingModeStrings;
      System::Windows::Forms::Timer^ timer1;
      Byte count;

   public:
      BufferingExample()
         : Form()
      {
         array<String^>^tempStrings = {"Draw to Form without OptimizedDoubleBufferring control style","Draw to Form using OptimizedDoubleBuffering control style","Draw to HDC for form"};
         bufferingModeStrings = tempStrings;

         // Configure the Form for this example.
         this->Text = "User double buffering";
         this->MouseDown += gcnew MouseEventHandler( this, &BufferingExample::MouseDownHandler );
         this->Resize += gcnew EventHandler( this, &BufferingExample::OnResize );
         this->SetStyle( static_cast<ControlStyles>(ControlStyles::AllPaintingInWmPaint | ControlStyles::UserPaint), true );

         // Configure a timer to draw graphics updates.
         timer1 = gcnew System::Windows::Forms::Timer;
         timer1->Interval = 200;
         timer1->Tick += gcnew EventHandler( this, &BufferingExample::OnTimer );
         bufferingMode = 2;
         count = 0;

         // Retrieves the BufferedGraphicsContext for the 
         // current application domain.
         context = BufferedGraphicsManager::Current;

         // Sets the maximum size for the primary graphics buffer
         // of the buffered graphics context for the application
         // domain.  Any allocation requests for a buffer larger 
         // than this will create a temporary buffered graphics 
         // context to host the graphics buffer.
         context->MaximumBuffer = System::Drawing::Size( this->Width + 1, this->Height + 1 );

         // Allocates a graphics buffer the size of this form
         // using the pixel format of the Graphics created by 
         // the Form.CreateGraphics() method, which returns a 
         // Graphics object that matches the pixel format of the form.
         grafx = context->Allocate( this->CreateGraphics(), Rectangle(0,0,this->Width,this->Height) );

         // Draw the first frame to the buffer.
         DrawToBuffer( grafx->Graphics );
      }

   private:
      void MouseDownHandler( Object^ /*sender*/, MouseEventArgs^ e )
      {
         if ( e->Button == ::MouseButtons::Right )
         {
            // Cycle the buffering mode.
            if ( ++bufferingMode > 2 )
                        bufferingMode = 0;

            // If the previous buffering mode used 
            // the OptimizedDoubleBuffering ControlStyle,
            // disable the control style.
            if ( bufferingMode == 1 )
                        this->SetStyle( ControlStyles::OptimizedDoubleBuffer, true );

            // If the current buffering mode uses
            // the OptimizedDoubleBuffering ControlStyle,
            // enabke the control style.
            if ( bufferingMode == 2 )
                        this->SetStyle( ControlStyles::OptimizedDoubleBuffer, false );

            // Cause the background to be cleared and redraw.
            count = 6;
            DrawToBuffer( grafx->Graphics );
            this->Refresh();
         }
         else
         {
            
            // Toggle whether the redraw timer is active.
            if ( timer1->Enabled )
                        timer1->Stop();
            else
                        timer1->Start();
         }
      }

   private:
      void OnTimer( Object^ /*sender*/, EventArgs^ /*e*/ )
      {
         // Draw randomly positioned ellipses to the buffer.
         DrawToBuffer( grafx->Graphics );

         // If in bufferingMode 2, draw to the form's HDC.
         if ( bufferingMode == 2 )

         // Render the graphics buffer to the form's HDC.
         grafx->Render( Graphics::FromHwnd( this->Handle ) );
         // If in bufferingMode 0 or 1, draw in the paint method.
         else

         // If in bufferingMode 0 or 1, draw in the paint method.
         this->Refresh();
      }

      void OnResize( Object^ /*sender*/, EventArgs^ /*e*/ )
      {
         // Re-create the graphics buffer for a new window size.
         context->MaximumBuffer = System::Drawing::Size( this->Width + 1, this->Height + 1 );
         if ( grafx != nullptr )
         {
            delete grafx;
            grafx = nullptr;
         }

         grafx = context->Allocate( this->CreateGraphics(), Rectangle(0,0,this->Width,this->Height) );

         // Cause the background to be cleared and redraw.
         count = 6;
         DrawToBuffer( grafx->Graphics );
         this->Refresh();
      }

      void DrawToBuffer( Graphics^ g )
      {
         // Clear the graphics buffer every five updates.
         if ( ++count > 5 )
         {
            count = 0;
            grafx->Graphics->FillRectangle( Brushes::Black, 0, 0, this->Width, this->Height );
         }

         // Draw randomly positioned and colored ellipses.
         Random^ rnd = gcnew Random;
         for ( int i = 0; i < 20; i++ )
         {
            int px = rnd->Next( 20, this->Width - 40 );
            int py = rnd->Next( 20, this->Height - 40 );
            g->DrawEllipse( gcnew Pen( Color::FromArgb( rnd->Next( 0, 255 ), rnd->Next( 0, 255 ), rnd->Next( 0, 255 ) ), 1.0f ), px, py, px + rnd->Next( 0, this->Width - px - 20 ), py + rnd->Next( 0, this->Height - py - 20 ) );
         }

         // Draw information strings.
         g->DrawString( String::Format( "Buffering Mode: {0}", bufferingModeStrings[ bufferingMode ] ), gcnew System::Drawing::Font( "Arial",8 ), Brushes::White, 10, 10 );
         g->DrawString( "Right-click to cycle buffering mode", gcnew System::Drawing::Font( "Arial",8 ), Brushes::White, 10, 22 );
         g->DrawString( "Left-click to toggle timed display refresh", gcnew System::Drawing::Font( "Arial",8 ), Brushes::White, 10, 34 );
      }

   protected:
      virtual void OnPaint( PaintEventArgs^ e ) override
      {
         grafx->Render( e->Graphics );
      }
   };
}

[STAThread]
int main()
{
   Application::Run( gcnew BufferingExample::BufferingExample );
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace BufferingExample 
{
    public class BufferingExample : Form
    {
        private BufferedGraphicsContext context;
        private BufferedGraphics grafx;

	private byte bufferingMode;
	private string[] bufferingModeStrings = 
		{ "Draw to Form without OptimizedDoubleBufferring control style",
		  "Draw to Form using OptimizedDoubleBuffering control style",
		  "Draw to HDC for form" };

	private System.Windows.Forms.Timer timer1;
	private byte count;

        public BufferingExample() : base()
        {
            // Configure the Form for this example.
            this.Text = "User double buffering";
            this.MouseDown += new MouseEventHandler(this.MouseDownHandler);
            this.Resize += new EventHandler(this.OnResize);
            this.SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true );

            // Configure a timer to draw graphics updates.
	    timer1 = new System.Windows.Forms.Timer();
	    timer1.Interval = 200;
	    timer1.Tick += new EventHandler(this.OnTimer);

	    bufferingMode = 2;
	    count = 0;

            // Retrieves the BufferedGraphicsContext for the 
            // current application domain.
            context = BufferedGraphicsManager.Current;

            // Sets the maximum size for the primary graphics buffer
            // of the buffered graphics context for the application
            // domain.  Any allocation requests for a buffer larger 
            // than this will create a temporary buffered graphics 
            // context to host the graphics buffer.
            context.MaximumBuffer = new Size(this.Width+1, this.Height+1);

            // Allocates a graphics buffer the size of this form
            // using the pixel format of the Graphics created by 
            // the Form.CreateGraphics() method, which returns a 
            // Graphics object that matches the pixel format of the form.
            grafx = context.Allocate(this.CreateGraphics(), 
                 new Rectangle( 0, 0, this.Width, this.Height ));

	    // Draw the first frame to the buffer.
	    DrawToBuffer(grafx.Graphics);
        }

	private void MouseDownHandler(object sender, MouseEventArgs e)
        {
	    if( e.Button == MouseButtons.Right )
	    {
                 // Cycle the buffering mode.
	         if( ++bufferingMode > 2 )
                     bufferingMode = 0;

                 // If the previous buffering mode used 
                 // the OptimizedDoubleBuffering ControlStyle,
                 // disable the control style.
                 if( bufferingMode == 1 )
                     this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );

                 // If the current buffering mode uses
                 // the OptimizedDoubleBuffering ControlStyle,
                 // enabke the control style.
                 if( bufferingMode == 2 )
                     this.SetStyle( ControlStyles.OptimizedDoubleBuffer, false );

                 // Cause the background to be cleared and redraw.
                 count = 6;
    	         DrawToBuffer(grafx.Graphics);                 
		 this.Refresh();
	    }
	    else
	    {
                // Toggle whether the redraw timer is active.
		if( timer1.Enabled )
			timer1.Stop();
		else
			timer1.Start(); 
	    }
        }

	private void OnTimer(object sender, EventArgs e)
	{
            // Draw randomly positioned ellipses to the buffer.
	    DrawToBuffer(grafx.Graphics);

            // If in bufferingMode 2, draw to the form's HDC.
	    if( bufferingMode == 2 )            
                    // Render the graphics buffer to the form's HDC.
		    grafx.Render(Graphics.FromHwnd(this.Handle));            
            // If in bufferingMode 0 or 1, draw in the paint method.
	    else
  		    this.Refresh();
	}

        private void OnResize(object sender, EventArgs e)
        {
           // Re-create the graphics buffer for a new window size.
           context.MaximumBuffer = new Size(this.Width+1, this.Height+1);
           if( grafx != null )
           {
	       grafx.Dispose();
               grafx = null;               
           }
           grafx = context.Allocate(this.CreateGraphics(), 
               new Rectangle( 0, 0, this.Width, this.Height ));
           
           // Cause the background to be cleared and redraw.
           count = 6;
    	   DrawToBuffer(grafx.Graphics);                 
	   this.Refresh();
        }	

	private void DrawToBuffer(Graphics g)
	{
            // Clear the graphics buffer every five updates.
	    if( ++count > 5 )
            {
                count = 0;                
                grafx.Graphics.FillRectangle(Brushes.Black, 0, 0, this.Width, this.Height);
            }

            // Draw randomly positioned and colored ellipses.
	    Random rnd = new Random();
	    for( int i=0; i<20; i++ )
	    {
		int px = rnd.Next(20,this.Width-40);
		int py = rnd.Next(20,this.Height-40);
		g.DrawEllipse(new Pen(Color.FromArgb(rnd.Next(0, 255), rnd.Next(0,255), rnd.Next(0,255)), 1), 
			px, py, px+rnd.Next(0, this.Width-px-20), py+rnd.Next(0, this.Height-py-20)); 	    			
	    }

            // Draw information strings.
	    g.DrawString("Buffering Mode: "+bufferingModeStrings[bufferingMode], new Font("Arial", 8), Brushes.White, 10, 10);
            g.DrawString("Right-click to cycle buffering mode", new Font("Arial", 8), Brushes.White, 10, 22);
            g.DrawString("Left-click to toggle timed display refresh", new Font("Arial", 8), Brushes.White, 10, 34);
	}

	protected override void OnPaint(PaintEventArgs e)
        {            
	    grafx.Render(e.Graphics);
	}

        [STAThread]
        public static void Main(string[] args)
        {
	    Application.Run(new BufferingExample());
        }
    }
}
Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms

Public Class BufferingExample
    Inherits Form
    Private context As BufferedGraphicsContext
    Private grafx As BufferedGraphics
    
    Private bufferingMode As Byte
    Private bufferingModeStrings As String() = _
        {"Draw to Form without OptimizedDoubleBufferring control style", _
         "Draw to Form using OptimizedDoubleBuffering control style", _
         "Draw to HDC for form"}
    
    Private timer1 As System.Windows.Forms.Timer
    Private count As Byte    
    
    Public Sub New()
        ' Configure the Form for this example.
        Me.Text = "User double buffering"
        AddHandler Me.MouseDown, AddressOf Me.MouseDownHandler
        AddHandler Me.Resize, AddressOf Me.ResizeHandler
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint, True)
        
        ' Configure a timer to draw graphics updates.
        timer1 = New System.Windows.Forms.Timer()
        timer1.Interval = 200
        AddHandler timer1.Tick, AddressOf Me.OnTimer
        
        bufferingMode = 2
        count = 0
        
        ' Retrieves the BufferedGraphicsContext for the 
        ' current application domain.
        context = BufferedGraphicsManager.Current
        
        ' Sets the maximum size for the primary graphics buffer
        ' of the buffered graphics context for the application
        ' domain.  Any allocation requests for a buffer larger 
        ' than this will create a temporary buffered graphics 
        ' context to host the graphics buffer.
        context.MaximumBuffer = New Size(Me.Width + 1, Me.Height + 1)
        
        ' Allocates a graphics buffer the size of this form
        ' using the pixel format of the Graphics created by 
        ' the Form.CreateGraphics() method, which returns a 
        ' Graphics object that matches the pixel format of the form.
        grafx = context.Allocate(Me.CreateGraphics(), _
            New Rectangle(0, 0, Me.Width, Me.Height))
        
        ' Draw the first frame to the buffer.
        DrawToBuffer(grafx.Graphics)
    End Sub    
    
    Private Sub MouseDownHandler(sender As Object, e As MouseEventArgs)
        If e.Button = MouseButtons.Right Then
            ' Cycle the buffering mode.
            bufferingMode = bufferingMode+1
            If bufferingMode > 2 Then
                bufferingMode = 0
            End If 
            ' If the previous buffering mode used 
            ' the OptimizedDoubleBuffering ControlStyle,
            ' disable the control style.
            If bufferingMode = 1 Then
                Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
            End If 
            ' If the current buffering mode uses
            ' the OptimizedDoubleBuffering ControlStyle,
            ' enabke the control style.
            If bufferingMode = 2 Then
                Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, False)
            End If 
            ' Cause the background to be cleared and redraw.
            count = 6
            DrawToBuffer(grafx.Graphics)
            Me.Refresh()
        Else
            ' Toggle whether the redraw timer is active.
            If timer1.Enabled Then
                timer1.Stop()
            Else
                timer1.Start()
            End If
        End If
    End Sub
     
    Private Sub OnTimer(sender As Object, e As EventArgs)
        ' Draw randomly positioned ellipses to the buffer.
        DrawToBuffer(grafx.Graphics)
        
        ' If in bufferingMode 2, draw to the form's HDC.
        If bufferingMode = 2 Then
            ' Render the graphics buffer to the form's HDC.
            grafx.Render(Graphics.FromHwnd(Me.Handle))
        ' If in bufferingMode 0 or 1, draw in the paint method.
        Else
            Me.Refresh()
        End If
    End Sub
     
    Private Sub ResizeHandler(sender As Object, e As EventArgs)
        ' Re-create the graphics buffer for a new window size.
        context.MaximumBuffer = New Size(Me.Width + 1, Me.Height + 1)
        If (grafx IsNot Nothing) Then
            grafx.Dispose()
            grafx = Nothing
        End If
        grafx = context.Allocate(Me.CreateGraphics(), New Rectangle(0, 0, Me.Width, Me.Height))
        
        ' Cause the background to be cleared and redraw.
        count = 6
        DrawToBuffer(grafx.Graphics)
        Me.Refresh()
    End Sub    
    
    Private Sub DrawToBuffer(g As Graphics)
        ' Clear the graphics buffer every five updates.
        count = count+1
        If count > 5 Then
            count = 0
            grafx.Graphics.FillRectangle(Brushes.Black, 0, 0, Me.Width, Me.Height)
        End If
        
        ' Draw randomly positioned and colored ellipses.
        Dim rnd As New Random()
        Dim i As Integer
        For i = 0 To 21
            Dim px As Integer = rnd.Next(20, Me.Width - 40)
            Dim py As Integer = rnd.Next(20, Me.Height - 40)
            g.DrawEllipse(New Pen(Color.FromArgb(rnd.Next(0, 255), rnd.Next(0, 255), _
                rnd.Next(0, 255)), 1), px, py, px + rnd.Next(0, Me.Width - px - 20), _
                py + rnd.Next(0, Me.Height - py - 20))
        Next i
        
        ' Draw information strings.
        g.DrawString("Buffering Mode: " + bufferingModeStrings(bufferingMode), _
            New Font("Arial", 8), Brushes.White, 10, 10)
        g.DrawString("Right-click to cycle buffering mode", New Font("Arial", 8), _
            Brushes.White, 10, 22)
        g.DrawString("Left-click to toggle timed display refresh", _
            New Font("Arial", 8), Brushes.White, 10, 34)
    End Sub    
    
    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        grafx.Render(e.Graphics)
    End Sub   
    
    <STAThread()>  _
    Public Shared Sub Main(args() As String)
        Application.Run(New BufferingExample())
    End Sub

End Class

注釈

BufferedGraphicsグラフィックスのカスタムのダブル バッファリングを実装するクラスを使用できます。The BufferedGraphics class allows you to implement custom double buffering for your graphics. バッファーに書き込むし、出力デバイスにコンテンツのレンダリングに使用できるメソッドと共にのグラフィックス バッファーのラッパーを提供します。It provides a wrapper for a graphics buffer, along with methods that you can use to write to the buffer and render its contents to an output device.

ダブル バッファリングを使用するグラフィックスでは、削減したり、表示画面を再描画によるちらつきすることができます。Graphics that use double buffering can reduce or eliminate flicker that is caused by redrawing a display surface. ダブル バッファリングを使用して、更新されたグラフィックスは最初に、メモリ内のバッファーに描画され、このバッファーの内容が表示される画面の一部またはすべてにすばやく書き込まれますし。When you use double buffering, updated graphics are first drawn to a buffer in memory, and the contents of this buffer are then quickly written to some or all of the displayed surface. 表示されるグラフィックスの比較的簡単なこの上書きを低減またはグラフィックスが更新されたときに発生しやすいちらつきがなくなります。This relatively brief overwrite of the displayed graphics typically reduces or eliminates the flicker that sometimes occurs when graphics are updated.

注意

ダブル バッファリングを使用する最も簡単な方法を設定するのには、OptimizedDoubleBuffer制御を使用してコントロールのスタイルのフラグ、SetStyleメソッド。The simplest way to use double buffering is to set the OptimizedDoubleBuffer control style flag on a control using the SetStyle method. 設定、OptimizedDoubleBufferコントロール、追加のコードを必要とせず、既定のグラフィックス バッファーを使用してコントロールのすべての描画のリダイレクトのフラグを設定します。Setting the OptimizedDoubleBuffer flag for a control redirects all painting for the control through a default graphics buffer, without requiring any additional code. このフラグに設定されてtrue既定。This flag is set to true by default.

BufferedGraphicsクラスのパブリック コンス トラクターを持たないし、によって作成する必要があります、BufferedGraphicsContextを使用してアプリケーション ドメイン、Allocateメソッド。The BufferedGraphics class has no public constructor and must be created by the BufferedGraphicsContext for an application domain using its Allocate method. 取得することができます、BufferedGraphicsContextの現在のアプリケーション ドメインを静的からBufferedGraphicsManager.Currentプロパティ。You can retrieve the BufferedGraphicsContext for the current application domain from the static BufferedGraphicsManager.Current property.

Graphicsプロパティは、グラフィックス バッファーへの描画に使用できます。The Graphics property can be used for drawing to the graphics buffer. このプロパティへのアクセスを提供する、Graphicsこの割り当てられたグラフィックス バッファーに描画オブジェクトBufferedGraphicsオブジェクト。This property provides access to the Graphics object that draws to the graphics buffer allocated for this BufferedGraphics object.

Renderを画面に、グラフィックスの内容をバッファーなし引数描画メソッドは、バッファーが割り当てられたを指定します。The Render method with no arguments draws the contents of the graphics buffer to the surface specified when the buffer was allocated. 他のオーバー ロード、Renderメソッドでは、指定すること、GraphicsオブジェクトまたはIntPtrグラフィックス バッファーの内容を描画するためにデバイス コンテキストを指しているオブジェクト。Other overloads of the Render method allow you to specify a Graphics object or an IntPtr object that points to a device context to which to draw the contents of the graphics buffer.

ダブル バッファリングされたグラフィックスの描画の詳細については、次を参照してください。ダブル バッファリングされたグラフィックスします。For more information about drawing double-buffered graphics, see Double Buffered Graphics.

プロパティ

Graphics Graphics Graphics Graphics

グラフィックス バッファーに出力する Graphics オブジェクトを取得します。Gets a Graphics object that outputs to the graphics buffer.

メソッド

Dispose() Dispose() Dispose() Dispose()

この BufferedGraphics オブジェクトによって使用されているすべてのリソースを解放します。Releases all resources used by the BufferedGraphics object.

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

指定したオブジェクトが、現在のオブジェクトと等しいかどうかを判断します。Determines whether the specified object is equal to the current object.

(Inherited from Object)
Finalize() Finalize() Finalize() Finalize()

オブジェクトが、ガベージ コレクションによって収集される前に、リソースの解放とその他のクリーンアップ操作の実行を試みることができるようにします。Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.

GetHashCode() GetHashCode() GetHashCode() GetHashCode()

既定のハッシュ関数として機能します。Serves as the default hash function.

(Inherited from Object)
GetType() GetType() GetType() GetType()

現在のインスタンスの Type を取得します。Gets the Type of the current instance.

(Inherited from Object)
MemberwiseClone() MemberwiseClone() MemberwiseClone() MemberwiseClone()

現在の Object の簡易コピーを作成します。Creates a shallow copy of the current Object.

(Inherited from Object)
Render() Render() Render() Render()

グラフィックス バッファーの内容を既定のデバイスに書き込みます。Writes the contents of the graphics buffer to the default device.

Render(Graphics) Render(Graphics) Render(Graphics) Render(Graphics)

グラフィックス バッファーの内容を指定された Graphics オブジェクトに書き込みます。Writes the contents of the graphics buffer to the specified Graphics object.

Render(IntPtr) Render(IntPtr) Render(IntPtr) Render(IntPtr)

グラフィックス バッファーの内容を、指定した IntPtr ハンドルに関連付けられているデバイス コンテキストに書き込みます。Writes the contents of the graphics buffer to the device context associated with the specified IntPtr handle.

ToString() ToString() ToString() ToString()

現在のオブジェクトを表す文字列を返します。Returns a string that represents the current object.

(Inherited from Object)

適用対象

スレッド セーフ

BufferedGraphics クラスはスレッド セーフではありません。The BufferedGraphics class is not thread safe. グラフィックス バッファーを別のスレッドからにアクセスするときは、スレッド アクセスの制御メカニズムを使用して、競合を回避する必要があります。When accessing a graphics buffer from separate threads, it is important to use a thread-access control mechanism to prevent conflicts.

こちらもご覧ください