Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp_Prog_Guide.doc
Скачиваний:
16
Добавлен:
16.11.2019
Размер:
6.22 Mб
Скачать

Использование потоков

По умолчанию программа на языке C# имеет один поток. Этот поток выполняет код при запуске и завершении программы с помощью метода Main. Каждая команда, выполняемая с помощью метода Main — прямо или косвенно — выполняется по умолчанию или посредством основного потока, и этот поток прекращает работу после возврата Main. Однако параллельно основному потоку могут создаваться и использоваться вспомогательные потоки. Эти потоки часто называются рабочими потоками.

Рабочие потоки могут использоваться для выполнения трудоемких или срочных задач без прерывания основного потока. Например, рабочие потоки часто используются в серверных приложениях для выполнения входящих запросов, не дожидаясь завершения выполнения предыдущего запроса. Рабочие потоки также используются для выполнения "фоновых" задач в настольных приложениях, что позволяет основному потоку (который отвечает за элементы пользовательского интерфейса) оставаться доступным для команд пользователя.

Многопоточность позволяет решить проблемы с пропускной способностью и быстротой ответа системы, однако при этом возникают проблемы совместного использования ресурсов, в частности взаимоблокировки и состояния гонки. Использование нескольких потоков лучше всего подходит для тех задач, которые используют различные ресурсы, например дескрипторы файлов и сетевые подключения. Назначение нескольких потоков одному ресурсу, вероятнее всего, вызовет проблемы синхронизации и частую блокировку потоков во время ожидания, что сведет к минимуму целесообразность использования нескольких потоков.

Обычно рабочие потоки используются для выполнения трудоемких или срочных задач, для которых не требуется большое количество ресурсов, используемых другими потоками. Естественно, некоторые используемые программой ресурсы должны быть доступны для нескольких потоков. В этих случаях пространство имен System.Threading предоставляет классы для синхронизации потоков. Эти классы включают Mutex, Monitor, Interlocked, AutoResetEvent и ManualResetEvent.

Можно использовать некоторые или все эти классы для синхронизации работы нескольких потоков, но некоторые многопоточные функции поддерживаются языком C#. Например, оператор Lock языка C# обеспечивает синхронизацию за счет неявного использования класса Monitor.

Thread Synchronization

The following sections describe features and classes that can be used to synchronize access to resources in multithreaded applications.

One of the benefits of using multiple threads in an application is that each thread executes asynchronously. For Windows applications, this allows time-consuming tasks to be performed in the background while the application window and controls remain responsive. For server applications, multithreading provides the ability to handle each incoming request with a different thread. Otherwise, each new request would not get serviced until the previous request had been fully satisfied.

However, the asynchronous nature of threads means that access to resources such as file handles, network connections, and memory must be coordinated. Otherwise, two or more threads could access the same resource at the same time, each unaware of the other's actions. The result is unpredictable data corruption.

For simple operations on integral numeric data types, synchronizing threads can be accomplished with members of the Interlocked class. For all other data types and non thread-safe resources, multithreading can only be safely performed using the constructs in this topic.

The lock Keyword

The lock keyword can be used to ensure that a block of code runs to completion without interruption by other threads. This is accomplished by obtaining a mutual-exclusion lock for a given object for the duration of the code block.

A lock statement begins with the keyword lock, which is given an object as an argument, and followed by a code block that is to be executed by only one thread at a time. For example:

public class TestThreading

{

private System.Object lockThis = new System.Object();

public void Function()

{

lock (lockThis)

{

// Access thread-sensitive resources.

}

}

}