
C# ПІДРУЧНИКИ / c# / MS Press - Msdn Training Programming Net Framework With C#
.pdfModule 14 (Optional): Threading and Asynchronous Programming |
93 |
|
|
|
|
Scenario
In this scenario, you use a Windows Forms client to invoke methods on a logger server that writes messages to a log file. When starting the logger server the client specifies the filename to use as a log file. After the logger server starts, it opens the log file and begins two concurrent operations. In the first operation, the server periodically writes the date and time to the log file; the server does this by using a System.Thread.Timer object that uses a thread from the thread pool.
In the second operation, the server periodically updates the client’s progress bar to indicate to the user that the logger service is running. The server does this by creating and starting a background thread. When the user stops the logger server, the server terminates both concurrent operations and closes the log file.
While the logger server is running, the client can invoke a synchronous or an asynchronous write of a text string to the log file. The asynchronous write is done according to the .NET Framework asynchronous design pattern. The client starts the asynchronous write by calling the BeginInvoke method of a delegate to the logger server’s write method. The client, as a parameter to this call, supplies an AsyncCallback delegate object that refers to the client’s method that is called when the write operation completes.
Because multiple client calls to the server can execute concurrently, the server’s methods must be implemented in a thread-safe manner.
Estimated time to complete this lab: 50 minutes

94 |
Module 14 (Optional): Threading and Asynchronous Programming |
Exercise 1
Creating Thread-safe Methods
In this exercise, you will add thread-safe code to the MyLogger static methods to start the logger, stop the logger, and write to the log file.
!Implement the StartLogger method
1.In Visual Studio .NET, open the Multithreading project which is located in <install folder>\Labs\Lab14\Starter.
2.Open the file Form1.cs and locate the following comment for the
StartLogger method of the MyLogger class:
// TODO - Exercise 1.1: Add code to start logger
Note You can use the Visual Studio .NET Task List window to quickly locate this code. To display this window, on the View menu, click Show Tasks, and click All.
3.Use a lock statement to ensure that only one thread at a time executes the method’s code.
Because StartLogger is a static method, you lock on the System.Type object of the MyLogger class. You can obtain this object by using the following expression:
typeof(MyLogger)
Place the remainder of the StartLogger method’s code within the lock statement block.
4.Create a conditional expression that evaluates whether the logger is running. If the logger is running, throw an InvalidOperationException exception. If the logger is not running (loggerRunning is false):
a.Initialize numberOfWrites to zero.
b.Create a FileStream object for the file that is specified in the filename parameter of the StartLogger method. The new FileStream object also takes the filename, FileMode.OpenOrCreate and FileAccess.Write parameters.
c.Create a StreamWriter object and pass in the new FileStream object. This new object should be assigned to the existing static member variable w.
d.Set the file pointer to the end of the new stream by calling the StreamWriter object’s seek method as follows:
w.BaseStream.Seek(0, SeekOrigin.End);
e.Write to the stream by using the following format and supplying the current time and date as the parameters:
"\nStartLogger – Time: {0} {1} \n\n"
Module 14 (Optional): Threading and Asynchronous Programming |
95 |
|
|
|
|
f.Flush the stream.
g.Set the existing static member variable form to the value of the parameter aForm in the StartLogger method.
h.Set the existing static member variable mi to a new delegate object of type MethodInvoker that refers to the form object’s UpdateProgress method.
i.Set loggerRunning to true.
! Implement the StopLogger method
1.In Form1.cs, locate the following comment for the StopLogger method of the MyLogger class:
// TODO - Exercise 1.2: Add code to stop logger
2.Use a lock statement to ensure that only one thread at a time executes the static method’s code.
Place the remainder of the StopLogger method’s code within the lock statement block.
3.Create a conditional expression that evaluates whether the logger is running. If the logger is not running, throw an InvalidOperationException exception. If the logger is running (loggerRunning is true):
a. Write to the stream by using the following format and supplying the current time and date as the parameters:
"\nStopLogger – Time: {0} {1} \n\n"
b.Close the stream.
c.Set loggerRunning to false.

96Module 14 (Optional): Threading and Asynchronous Programming
!Implement the WriteLog method
1.In Form1.cs, locate the following comment for the WriteLog method of the
MyLogger class:
//TODO - Exercise 1.3: Add code to write to logger
2.Use a lock statement to ensure that only one thread at a time executes the static method’s code.
Place the remainder of the WriteLog method’s code within the lock statement block.
3.Create a variable of type int that is named writeCount and initialize it to the value of numberOfWrites.
4.Create a conditional expression that evaluates whether the logger is running. If the logger is not running, throw an InvalidOperationException exception. If the logger is running (loggerRunning is true):
a.Make the thread sleep for 2 seconds.
b.Increment the value of writeCount by 1.
c.Write to the stream by using the following format and supplying writeCount and logText as the parameters:
"\nCount: {0} Text: {1} - Time:"
d. Write to the stream by using the following format and supplying the current time and date as the parameters:
"{0} {1} \n\n"
e.Flush the stream.
f.Set numberOfWrites to the value of writeCount.
5.Return writeCount.
Module 14 (Optional): Threading and Asynchronous Programming |
97 |
|
|
|
|
! Test the application
1.Build and run the application by using Visual Studio .NET. Ignore warning messages about fields that are never used.
2.In the Text To Log field, type Hello World.
3.To check the error reporting, click Synchronous Write, and note the following message in the status bar at the bottom of the form:
“Invalid Operation - Write failed because logger was stopped”
4.Click Start Logger, and note the Logger State Indicator progress bar and the following message in the status bar:
“Logger started”
5.Click Synchronous Write, and note that after a pause of 2 seconds the following message is displayed in the status bar:
“Log written, count = 1”
6.Click Synchronous Write, and note that after a pause of 2 seconds the following message is displayed in the status bar:
“Log written, count = 2”
7.Click Stop Logger, and note that the message in the status bar now says: “Logger stopped”
8.Use Visual Studio .NET to view the log file Log.txt, that was created in the same folder as the multithreading application’s executable program:
<install folder>\Labs\Lab14\Starter\Multithreading\bin\Debug You should see output that is similar to the following:
StartLogger - Time: 11:09:48 AM Wednesday, September 19, 2001
Count:1 Text: Hello World - Time:11:10:40 AM Wednesday,
September 19, 2001
Count:2 Text: Hello World - Time:11:11:30 AM Wednesday,
September 19, 2001
StopLogger - Time:11:11:56 AM Wednesday, September 19, 2001
9. Stop the application and delete Log.txt.
Module 14 (Optional): Threading and Asynchronous Programming |
99 |
|
|
|
|
! Test the application
1.Build and run the application by using Visual Studio .NET. Ignore warning messages about fields that are never used. Ensure that you have deleted the file Log.txt that was created in the preceding exercise.
2.In the Text To Log field, type Hello World.
3.Click Start Logger, and note the following message in the status bar: “Logger started”
4.Click Synchronous Write, and note that after a pause of 2 seconds the following message is displayed in the status bar:
“Log written, count = 1”
5.Click Synchronous Write, and note that after a pause of 2 seconds the message in the status bar changes to:
“Log written, count = 2”
6.Click the Stop Logger button and note that the message in the status bar now says;
“Logger stopped”
7.Use Visual Studio .NET to view the file Log.txt that was created in the same folder as the multithreading application’s executable program:
<install folder>\Labs\Lab14\Starter\Multithreading\bin\Debug You should see output that is similar to the following:
StartLogger - Time: 11:47:21 AM Wednesday, September 19, 2001
Logger Alive: 11:47:21 AM Wednesday, September 19, 2001
Count:1 Text: Hello World - Time:11:47:24 AM Wednesday,
September 19, 2001
Logger Alive: 11:47:26 AM Wednesday, September 19, 2001
Count:2 Text: Hello World - Time:11:47:27 AM Wednesday,
September 19, 2001
StopLogger - Time:11:47:28 AM Wednesday, September 19, 2001
8. Stop the application and delete Log.txt.
Module 14 (Optional): Threading and Asynchronous Programming |
101 |
|
|
|
|
! Advance the form’s progress bar periodically
1.In Form1.cs, locate the following comment for the ThreadProc method of the MyLogger class:
// TODO - Exercise 3.3: Add code to update the client's! progress indicator
2.In a try/catch block’s try section, insert a while(true) statement whose block contains the following steps:
a. Call the form object’s BeginInvoke method.
Pass as the BeginInvoke method’s parameter the delegate object of type
MethodInvoker that refers to the form object’s UpdateProgress method. This object was created in the StartLogger method and is named mi.
b.Make the thread sleep for ½ second.
3.In the try/catch block’s catch section add code to do the following:
a.Catch exceptions of the type ThreadInterruptedException.
b.Within the catch block, do nothing.
This will resolve the exception and the thread will terminate gracefully.
! Test the application
1.Build and run the application by using Visual Studio .NET. Ensure that you have deleted the file Log.txt that was created in the preceding exercise.
2.In the Text To Log field, type Hello World.
3.Click Start Logger.
Note that the Logger State Indicator progress bar is advancing and note the following message in the status bar.
“Logger started”
4.Click Synchronous Write, and note that the progress bar stops advancing.
After a pause of 2 seconds, the progress bar jumps ahead and the following message is displayed in the status bar.
“Log written, count = 1”
5.Click Synchronous Write, and note that the progress bar stops advancing.
After a pause of 2 seconds, the progress bar jumps ahead and the following message is displayed in the status bar.
“Log written, count = 2”
6.Click Stop Logger.
Note that the Logger State Indicator progress bar has stopped advancing and note that the message in the status bar now says:
“Logger stopped”