}

 } catch (ThreadAbortException ex) {

  Console.WriteLine(ex.Message);

 } finally {

  //---clean up your resources here---

 }

}

To invoke DoSomething() as a thread and pass it a parameter, you use the ParameterizedThreadStart delegate as follows:

static void Main(string[] args) {

 Thread t = new Thread(new ParameterizedThreadStart(DoSomething));

 t.Start('useful');

 Console.WriteLine('Continuing with the execution...');

 ...

The argument to pass to the function is passed in the Start() method.

Thread Synchronization

Multithreading enables you to have several threads of execution running at the same time. However, when a number of different threads run at the same time, they all compete for the same set of resources, so there must be a mechanism to ensure synchronization and communication among threads.

One key problem with multithreading is thread safety. Consider the following subroutine:

static void IncrementVar() {

 _value += 1;

}

If two threads execute the same routine at the same time, it is possible that _value variable will not be incremented correctly. One thread may read the value for _value and increment the value by 1. Before the incremented value can be updated, another thread may read the old value and increment it. In the end, _value is incremented only once. For instances like this, it is important that when _value is incremented, no other threads can access the region of the code that is doing the incrementing. You accomplish that by locking all other threads during an incrementation.

In C#, you can use the following ways to synchronize your threads:

□ The Interlocked class

□ The C# lock keyword

□ The Monitor class

The following sections discuss each of these. 

Using Interlocked Class

Because incrementing and decrementing are such common operations in programming, the .NET Framework class library provides the Interlocked class for performing atomic operations for variables that are shared by multiple threads. You can rewrite the preceding example using the Increment() method from the static Interlocked class:

static void IncrementVar() {

 Interlocked.Increment(ref _value);

}

You need to pass in the variable to be incremented by reference to the Increment() method. When a thread encounters the Increment() statement, all other threads executing the same statement must wait until the incrementing is done.

The Interlocked class also includes the Decrement() class that, as its name implies, decrements the specified variable by one.

Using C# Lock

The Interlocked class is useful when you are performing atomic increment or decrement operations. What happens if you have multiple statements that you need to perform atomically? Take a look at the following program:

class Program {

 //---initial balance amount---

 static int balance = 500;

 static void Main(string[] args) {

  Thread t1 = new Thread(new ThreadStart(Debit));

  t1.Start();

  Thread t2 = new Thread(new ThreadStart(Credit));

  t2.Start();

  Console.ReadLine();

 }

 static void Credit() {

  //---credit 1500---

  for (int i = 0; i < 15; i++) {

   balance += 100;

   Console.WriteLine('After crediting, balance is {0}', balance);

  }

 }

 static void Debit() {

  //---debit 1000---

  for (int i = 0; i < 10; i++) {

   balance -= 100;

   Console.WriteLine('After debiting, balance is {0}', balance);

  }

 }

}

Here two separate threads are trying to modify the value of balance. The Credit () function increments balance by 1500 in 15 steps of 100 each, and the Debit() function decrements balance by 1000 in 10 steps of 100 each. After each crediting or debiting you also print out the value of balance. With the two threads executing in parallel, it is highly probably that different threads may execute different parts of the functions at the same time, resulting in the inconsistent value of the balance variable.

Figure 10-5 shows one possible outcome of the execution. Notice that some of the lines showing the balance amount are inconsistent — the first two lines show that after crediting twice, the balance is still 500, and further down the balance jumps from 1800 to 400 and then back to 1700. In a correctly working scenario, the

Вы читаете C# 2008 Programmer's Reference
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату