Csharp/C Sharp/Thread/Thread Sync
Содержание
- 1 Another way to use lock to synchronize access to an object
- 2 A synchronized shared buffer implementation
- 3 Asynchronous Calls:A Simple Example 1
- 4 Asynchronous Calls:A Simple Example 2
- 5 Asynchronous Calls:Return Values
- 6 Asynchronous Calls:Waiting for Completion
- 7 Asynchronous Calls:Waiting for Completion 2
- 8 Data Protection and Synchronization:A Slightly Broken Example
- 9 illustrates the use of the Mutex object
- 10 My Main Class Async Call back
- 11 MyMain Class Async Wait Timeout
- 12 Threading and Asynchronous Operations:Access Reordering and Volatile
- 13 Threading Class Mutex
- 14 Use lock to synchronize access to an object
- 15 Use MethodImplAttribute to synchronize a method
- 16 Use Wait() and Pulse() to create a ticking clock
Another way to use lock to synchronize access to an object
<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852
- /
// Another way to use lock to synchronize access to an object.
using System; using System.Threading;
class SumArray {
int sum; public int sumIt(int[] nums) { sum = 0; // reset sum for(int i=0; i < nums.Length; i++) { sum += nums[i]; Console.WriteLine("Running total for " + Thread.CurrentThread.Name + " is " + sum); Thread.Sleep(10); // allow task-switch } return sum; }
}
class MyThread {
public Thread thrd; int[] a; int answer; /* Create one SumArray object for all instances of MyThread. */ static SumArray sa = new SumArray(); // Construct a new thread. public MyThread(string name, int[] nums) { a = nums; thrd = new Thread(new ThreadStart(this.run)); thrd.Name = name; thrd.Start(); // start the thread } // Begin execution of new thread. void run() { Console.WriteLine(thrd.Name + " starting."); // Lock calls to sumIt(). lock(sa) answer = sa.sumIt(a); Console.WriteLine("Sum for " + thrd.Name + " is " + answer); Console.WriteLine(thrd.Name + " terminating."); }
}
public class Sync2 {
public static void Main() { int[] a = {1, 2, 3, 4, 5}; MyThread mt1 = new MyThread("Child #1", a); MyThread mt2 = new MyThread("Child #2", a); mt1.thrd.Join(); mt2.thrd.Join(); }
}
</source>
<source lang="csharp">
using System; using System.Threading; public class SynchronizedBuffer {
private int buffer = -1; private int occupiedBufferCount = 0; public int Buffer { get { Monitor.Enter( this ); if ( occupiedBufferCount == 0 ) { Console.WriteLine(Thread.CurrentThread.Name + " tries to read." ); DisplayState( "Buffer empty. " +Thread.CurrentThread.Name + " waits." ); Monitor.Wait( this ); } --occupiedBufferCount; DisplayState( Thread.CurrentThread.Name + " reads " + buffer ); Monitor.Pulse( this ); int bufferCopy = buffer; Monitor.Exit( this ); return bufferCopy; } set { Monitor.Enter( this ); if ( occupiedBufferCount == 1 ) { Console.WriteLine(Thread.CurrentThread.Name + " tries to write." ); DisplayState( "Buffer full. " + Thread.CurrentThread.Name + " waits." ); Monitor.Wait( this ); } buffer = value; ++occupiedBufferCount; DisplayState( Thread.CurrentThread.Name + " writes " + buffer ); Monitor.Pulse( this ); Monitor.Exit( this ); } } public void DisplayState( string operation ) { Console.WriteLine( "{0,-35}{1,-9}{2}\n",operation, buffer, occupiedBufferCount ); } static void Main( string[] args ) { SynchronizedBuffer shared = new SynchronizedBuffer(); Random random = new Random(); Console.WriteLine( "{0,-35}{1,-9}{2}\n","Operation", "Buffer", "Occupied Count" ); shared.DisplayState( "Initial state" ); Producer producer = new Producer( shared, random ); Consumer consumer = new Consumer( shared, random ); Thread producerThread = new Thread( new ThreadStart( producer.Produce ) ); producerThread.Name = "Producer"; Thread consumerThread = new Thread( new ThreadStart( consumer.Consume ) ); consumerThread.Name = "Consumer"; producerThread.Start(); consumerThread.Start(); }
} public class Consumer {
private SynchronizedBuffer sharedLocation; private Random randomSleepTime; public Consumer( SynchronizedBuffer shared, Random random ) { sharedLocation = shared; randomSleepTime = random; } public void Consume() { int sum = 0; for ( int count = 1; count <= 10; count++ ) { Thread.Sleep( randomSleepTime.Next( 1, 1001 ) ); sum += sharedLocation.Buffer; } Console.WriteLine("{0} read values totaling: {1}.\nTerminating {0}.",Thread.CurrentThread.Name, sum ); }
} public class Producer {
private SynchronizedBuffer sharedLocation; private Random randomSleepTime; public Producer( SynchronizedBuffer shared, Random random ) { sharedLocation = shared; randomSleepTime = random; } public void Produce() { for ( int count = 1; count <= 10; count++ ) { Thread.Sleep( randomSleepTime.Next( 1, 1001 ) ); sharedLocation.Buffer = count; } Console.WriteLine( "{0} done producing.\nTerminating {0}.",Thread.CurrentThread.Name ); }
}
</source>
Asynchronous Calls:A Simple Example 1
<source lang="csharp">
/* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3
- /
// 29 - Threading and Asynchronous Operations\Asynchronous Calls\A Simple Example // copyright 2000 Eric Gunnerson using System;
public class AsynchronousCallsASimpleExample {
public static void Main() { AsyncCaller ac = new AsyncCaller(); ac.CallWriteLine("Hello"); }
} public class AsyncCaller {
// Declare a delegate that will match Console.WriteLine("string"); delegate void FuncToCall(string s); public void CallWriteLine(string s) { // delegate points to function to call // start the async call // wait for completion FuncToCall func = new FuncToCall(Console.WriteLine); IAsyncResult iar = func.BeginInvoke(s, null, null); func.EndInvoke(iar); }
}
</source>
Asynchronous Calls:A Simple Example 2
<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3
- /
// 29 - Threading and Asynchronous Operations\Asynchronous Calls\A Simple Example // copyright 2000 Eric Gunnerson using System; public class AsynchronousCallsASimpleExample2 {
public static void Main() { AsyncCaller ac = new AsyncCaller(); ac.CallWriteLineWithCallback("Hello There"); System.Threading.Thread.Sleep(1000); }
} public class AsyncCaller {
// Declare a delegate that will match Console.WriteLine("string"); delegate void FuncToCall(string s); public void WriteLineCallback(IAsyncResult iar) { Console.WriteLine("In WriteLineCallback"); FuncToCall func = (FuncToCall) iar.AsyncState; func.EndInvoke(iar); } public void CallWriteLineWithCallback(string s) { FuncToCall func = new FuncToCall(Console.WriteLine); func.BeginInvoke(s, new AsyncCallback(WriteLineCallback), func); // shows up as iar.AsyncState in callback }
}
</source>
Asynchronous Calls:Return Values
<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3
- /
// 29 - Threading and Asynchronous Operations\Asynchronous Calls\Return Values // copyright 2000 Eric Gunnerson using System; using System.Threading;
public class AsynchronousCallsReturnValues {
public static void Main() { AsyncCaller ac = new AsyncCaller(); ac.CallMathCallback(new AsyncCaller.MathFunctionToCall(Math.Sin), 0.0, 1.0, 0.2); Thread.Sleep(2000); }
} public class AsyncCaller {
public delegate double MathFunctionToCall(double arg); public void MathCallback(IAsyncResult iar) { MathFunctionToCall mc = (MathFunctionToCall) iar.AsyncState; double result = mc.EndInvoke(iar); Console.WriteLine("Function value = {0}", result); } public void CallMathCallback(MathFunctionToCall mathFunc, double start, double end, double increment) { AsyncCallback cb = new AsyncCallback(MathCallback); while (start < end) { Console.WriteLine("BeginInvoke: {0}", start); mathFunc.BeginInvoke(start, cb, mathFunc); start += increment; } }
}
</source>
Asynchronous Calls:Waiting for Completion
<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3
- /
// 29 - Threading and Asynchronous Operations\Asynchronous Calls\Waiting for Completion // copyright 2000 Eric Gunnerson using System; using System.Threading;
public class AsynchronousCallsWaitingforCompletion1 {
public static double DoCalculation(double value) { Console.WriteLine("DoCalculation: {0}", value); Thread.Sleep(250); return(Math.Cos(value)); } public static void Main() { AsyncCaller ac = new AsyncCaller(); ac.CallMathCallback(new AsyncCaller.MathFunctionToCall(DoCalculation)); //Thread.Sleep(500); // no longer needed }
} public class AsyncCaller {
public delegate double MathFunctionToCall(double arg); public void MathCallback(IAsyncResult iar) { MathFunctionToCall mc = (MathFunctionToCall) iar.AsyncState; double result = mc.EndInvoke(iar); Console.WriteLine("Function value = {0}", result); } WaitHandle DoInvoke(MathFunctionToCall mathFunc, double value) { AsyncCallback cb = new AsyncCallback(MathCallback); IAsyncResult asyncResult = mathFunc.BeginInvoke(value, cb, mathFunc); return(asyncResult.AsyncWaitHandle); } public void CallMathCallback(MathFunctionToCall mathFunc) { WaitHandle[] waitArray = new WaitHandle[4]; Console.WriteLine("Begin Invoke"); waitArray[0] = DoInvoke(mathFunc, 0.1); waitArray[1] = DoInvoke(mathFunc, 0.5); waitArray[2] = DoInvoke(mathFunc, 1.0); waitArray[3] = DoInvoke(mathFunc, 3.14159); Console.WriteLine("Begin Invoke Done"); Console.WriteLine("Waiting for completion"); WaitHandle.WaitAll(waitArray, 10000, false); Console.WriteLine("Completion achieved"); }
}
</source>
Asynchronous Calls:Waiting for Completion 2
<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3
- /
// 29 - Threading and Asynchronous Operations\Asynchronous Calls\Waiting for Completion // copyright 2000 Eric Gunnerson using System; using System.Threading;
public class AsynchronousCallsWaitingforCompletion2 {
public static double DoCalculation(double value) { Console.WriteLine("DoCalculation: {0}", value); Thread.Sleep(250); return(Math.Cos(value)); } public static void Main() { AsyncCaller ac = new AsyncCaller(); ac.CallMathCallback(new AsyncCaller.MathFunctionToCall(DoCalculation)); }
} public class AsyncCallTracker {
Delegate function; AutoResetEvent doneEvent; public AutoResetEvent DoneEvent { get { return(doneEvent); } } public Delegate Function { get { return(function); } } public AsyncCallTracker(Delegate function) { this.function = function; doneEvent = new AutoResetEvent(false); }
} public class AsyncCaller {
public delegate double MathFunctionToCall(double arg); public void MathCallback(IAsyncResult iar) { AsyncCallTracker callTracker = (AsyncCallTracker) iar.AsyncState; MathFunctionToCall func = (MathFunctionToCall) callTracker.Function; double result = func.EndInvoke(iar); Console.WriteLine("Function value = {0}", result); callTracker.DoneEvent.Set(); } WaitHandle DoInvoke(MathFunctionToCall mathFunc, double value) { AsyncCallTracker callTracker = new AsyncCallTracker(mathFunc); AsyncCallback cb = new AsyncCallback(MathCallback); IAsyncResult asyncResult = mathFunc.BeginInvoke(value, cb, callTracker); return(callTracker.DoneEvent); } public void CallMathCallback(MathFunctionToCall mathFunc) { WaitHandle[] waitArray = new WaitHandle[4]; Console.WriteLine("Begin Invoke"); waitArray[0] = DoInvoke(mathFunc, 0.1); waitArray[1] = DoInvoke(mathFunc, 0.5); waitArray[2] = DoInvoke(mathFunc, 1.0); waitArray[3] = DoInvoke(mathFunc, 3.14159); Console.WriteLine("Begin Invoke Done"); Console.WriteLine("Waiting for completion"); WaitHandle.WaitAll(waitArray, 10000, false); Console.WriteLine("Completion achieved"); }
}
</source>
Data Protection and Synchronization:A Slightly Broken Example
<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3
- /
// 29 - Threading and Asynchronous Operations\Data Protection and Synchronization\A Slightly Broken Example // copyright 2000 Eric Gunnerson using System; using System.Threading; class Val {
int number = 1; public void Bump() { int temp = number; number = temp + 2; } public override string ToString() { return(number.ToString()); } public void DoBump() { for (int i = 0; i < 5; i++) { Bump(); Console.WriteLine("number = {0}", number); } }
} public class DataProtectionandSynchronizationASlightlyBrokenExample {
public static void Main() { Val v = new Val(); for (int threadNum = 0; threadNum < 5; threadNum++) { Thread thread = new Thread(new ThreadStart(v.DoBump)); thread.Start(); } }
}
</source>
illustrates the use of the Mutex object
<source lang="csharp"> /* Mastering Visual C# .NET by Jason Price, Mike Gunderloy Publisher: Sybex; ISBN: 0782129110
- /
/*
Example14_11.cs illustrates the use of the Mutex object
- /
using System; using System.Threading; public class Example14_11 {
// a shared counter private static int Runs = 0; // a mutex static Mutex mtx; // the CountUp method increments the shared counter public static void CountUp() { while (Runs < 10) { // acquire the mutex mtx.WaitOne(); int Temp = Runs; Temp++; Console.WriteLine(Thread.CurrentThread.Name + " " + Temp); Thread.Sleep(1000); Runs = Temp; // release the mutex mtx.ReleaseMutex(); } } public static void Main() { // create the mutex mtx = new Mutex(false, "RunsMutex"); // create and launch two threads Thread t2 = new Thread(new ThreadStart(CountUp)); t2.Name = "t2"; Thread t3 = new Thread(new ThreadStart(CountUp)); t3.Name = "t3"; t2.Start(); t3.Start(); }
}
</source>
My Main Class Async Call back
<source lang="csharp"> /*
* C# Programmers Pocket Consultant * Author: Gregory S. MacBeth * Email: gmacbeth@comporium.net * Create Date: June 27, 2003 * Last Modified Date: * Version: 1 */
using System; using System.Threading; using System.Runtime.Remoting.Messaging; namespace Client.Chapter_15___Threading {
public class MyMainClassAsyncCallback { delegate int MyDelegate(string s, ref int a, ref int b); static void Main(string[] args) { MyDelegate X = new MyDelegate(DoSomething); int a = 0; int b = 0; //Making Async Call that calls a callback when finished AsyncCallback cb = new AsyncCallback(DoSomething2); IAsyncResult ar = X.BeginInvoke("Hello", ref a, ref b, cb, null); Console.ReadLine(); } //My Async Method static int DoSomething(string s, ref int a, ref int b) { a = 10; b = 100; Console.WriteLine("Fired! DoSomething1"); return 0; } //Mycallback method when finished running DoSomehting static void DoSomething2(IAsyncResult ar) { int a = 0; int b = 0; Console.WriteLine("Fired! DoSomething2"); //Get the delegate MyDelegate X = (MyDelegate)((AsyncResult)ar).AsyncDelegate; //get results X.EndInvoke(ref a, ref b, ar); Console.WriteLine(a); Console.WriteLine(b); } }
}
</source>
MyMain Class Async Wait Timeout
<source lang="csharp"> /*
* C# Programmers Pocket Consultant * Author: Gregory S. MacBeth * Email: gmacbeth@comporium.net * Create Date: June 27, 2003 * Last Modified Date: * Version: 1 */
using System; using System.Runtime.Remoting.Messaging; namespace Client.Chapter_15___Threading {
public class MyMainClassAsyncWaitTimeout { delegate int MyDelegate(string s, ref int a, ref int b); static void Main(string[] args) { MyDelegate X = new MyDelegate(DoSomething); int a = 0; int b = 0; IAsyncResult ar = X.BeginInvoke("Hello", ref a, ref b, null, null); ar.AsyncWaitHandle.WaitOne(10000, false); if (ar.IsCompleted) { int c = 0; int d = 0; //get results X.EndInvoke(ref c, ref d, ar); Console.WriteLine(c); Console.WriteLine(d); } } //My Async Method static int DoSomething(string s, ref int a, ref int b) { a = 10; b = 100; Console.WriteLine("Fired! DoSomething1"); return 0; } }
}
</source>
Threading and Asynchronous Operations:Access Reordering and Volatile
<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3
- /
// 29 - Threading and Asynchronous Operations\Access Reordering and Volatile // copyright 2000 Eric Gunnerson using System; using System.Threading; class Problem {
int x; int y; int curx; int cury; public Problem() { x = 0; y = 0; } public void Process1() { x = 1; cury = y; } public void Process2() { y = 1; curx = x; } public void TestCurrent() { Console.WriteLine("curx, cury: {0} {1}", curx, cury); }
} public class AccessReorderingandVolatile {
public static void Main() { Problem p = new Problem(); Thread t1 = new Thread(new ThreadStart(p.Process1)); Thread t2 = new Thread(new ThreadStart(p.Process2)); t1.Start(); t2.Start(); t1.Join(); t2.Join(); p.TestCurrent(); }
}
</source>
Threading Class Mutex
<source lang="csharp"> /*
* C# Programmers Pocket Consultant * Author: Gregory S. MacBeth * Email: gmacbeth@comporium.net * Create Date: June 27, 2003 * Last Modified Date: * Version: 1 */
using System; using System.Collections; using System.Threading; namespace Client.Chapter_15___Threading {
public class ThreadingClassMutex { public static Thread ThreadOne = new Thread(new ThreadStart(MutexExample)); public static ArrayList MyList = new ArrayList(); private static Mutex MyMutex = new Mutex(false, "MyMutex"); public ThreadingClassMutex() { MyList.Add("Test1"); MyList.Add("Test2"); } static void Main(string[] args) { ThreadOne.Start(); } protected static void MutexExample() { MyMutex.WaitOne(); MyList.Add("Test3"); MyMutex.ReleaseMutex(); } }
}
</source>
Use lock to synchronize access to an object
<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852
- /
// Use lock to synchronize access to an object.
using System; using System.Threading;
class SumArray {
int sum; public int sumIt(int[] nums) { lock(this) { // lock the entire method sum = 0; // reset sum for(int i=0; i < nums.Length; i++) { sum += nums[i]; Console.WriteLine("Running total for " + Thread.CurrentThread.Name + " is " + sum); Thread.Sleep(10); // allow task-switch } return sum; } }
}
class MyThread {
public Thread thrd; int[] a; int answer; /* Create one SumArray object for all instances of MyThread. */ static SumArray sa = new SumArray(); // Construct a new thread. public MyThread(string name, int[] nums) { a = nums; thrd = new Thread(new ThreadStart(this.run)); thrd.Name = name; thrd.Start(); // start the thread } // Begin execution of new thread. void run() { Console.WriteLine(thrd.Name + " starting."); answer = sa.sumIt(a); Console.WriteLine("Sum for " + thrd.Name + " is " + answer); Console.WriteLine(thrd.Name + " terminating."); }
}
public class Sync {
public static void Main() { int[] a = {1, 2, 3, 4, 5}; MyThread mt1 = new MyThread("Child #1", a); MyThread mt2 = new MyThread("Child #2", a); mt1.thrd.Join(); mt2.thrd.Join(); }
}
</source>
Use MethodImplAttribute to synchronize a method
<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852
- /
// Use MethodImplAttribute to synchronize a method.
using System; using System.Threading; using System.Runtime.rupilerServices;
class TickTock {
/* The following attribute synchronizes the entire tick() method. */ [MethodImplAttribute(MethodImplOptions.Synchronized)] public void tick(bool running) { if(!running) { // stop the clock Monitor.Pulse(this); // notify any waiting threads return; } Console.Write("Tick "); Monitor.Pulse(this); // let tock() run Monitor.Wait(this); // wait for tock() to complete } /* The following attribute synchronizes the entire tock() method. */ [MethodImplAttribute(MethodImplOptions.Synchronized)] public void tock(bool running) { if(!running) { // stop the clock Monitor.Pulse(this); // notify any waiting threads return; } Console.WriteLine("Tock"); Monitor.Pulse(this); // let tick() run Monitor.Wait(this); // wait for tick to complete }
}
class MyThread {
public Thread thrd; TickTock ttOb; // Construct a new thread. public MyThread(string name, TickTock tt) { thrd = new Thread(new ThreadStart(this.run)); ttOb = tt; thrd.Name = name; thrd.Start(); } // Begin execution of new thread. void run() { if(thrd.Name == "Tick") { for(int i=0; i<5; i++) ttOb.tick(true); ttOb.tick(false); } else { for(int i=0; i<5; i++) ttOb.tock(true); ttOb.tock(false); } }
}
public class TickingClock1 {
public static void Main() { TickTock tt = new TickTock(); MyThread mt1 = new MyThread("Tick", tt); MyThread mt2 = new MyThread("Tock", tt); mt1.thrd.Join(); mt2.thrd.Join(); Console.WriteLine("Clock Stopped"); }
}
</source>
Use Wait() and Pulse() to create a ticking clock
<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852
- /
// Use Wait() and Pulse() to create a ticking clock.
using System; using System.Threading;
class TickTock {
public void tick(bool running) { lock(this) { if(!running) { // stop the clock Monitor.Pulse(this); // notify any waiting threads return; } Console.Write("Tick "); Monitor.Pulse(this); // let tock() run Monitor.Wait(this); // wait for tock() to complete } } public void tock(bool running) { lock(this) { if(!running) { // stop the clock Monitor.Pulse(this); // notify any waiting threads return; } Console.WriteLine("Tock"); Monitor.Pulse(this); // let tick() run Monitor.Wait(this); // wait for tick to complete } }
}
class MyThread {
public Thread thrd; TickTock ttOb; // Construct a new thread. public MyThread(string name, TickTock tt) { thrd = new Thread(new ThreadStart(this.run)); ttOb = tt; thrd.Name = name; thrd.Start(); } // Begin execution of new thread. void run() { if(thrd.Name == "Tick") { for(int i=0; i<5; i++) ttOb.tick(true); ttOb.tick(false); } else { for(int i=0; i<5; i++) ttOb.tock(true); ttOb.tock(false); } }
}
public class TickingClock {
public static void Main() { TickTock tt = new TickTock(); MyThread mt1 = new MyThread("Tick", tt); MyThread mt2 = new MyThread("Tock", tt); mt1.thrd.Join(); mt2.thrd.Join(); Console.WriteLine("Clock Stopped"); }
}
</source>