Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Асинхронный файловый ввод-вывод.



Синхронный ввод и вывод означает, что метод блокируется до тех пор, пока операция ввода или вывода не будет завершена. Затем метод возвращает данные. С помощью асинхронного ввода и вывода пользователь может вызвать метод BeginRead. Основной поток продолжать выполнять другие операции и получает возможность обработки данных позже. Также множественные запросы ввода и вывода могут обрабатываться одновременно.

Чтобы определить доступность данных, можно вызвать метод EndRead или EndWrite, передавая IAsyncResult в соответствующий запрос ввода и вывода. Можно также указать метод обратного вызова, который будет вызывать метод EndRead или EndWrite, чтобы выяснить какое количество байтов было считано или записано. Асинхронные ввод и вывод являются более эффективными в том случае, когда одновременно обрабатывается большое количество запросов на ввод и вывод, но, как правило, они требуют значительных изменений в приложении для обеспечения его корректной работы.

Класс Stream поддерживает объединение синхронных и асинхронных операций чтения и записи в один поток независимо от того, допустимо ли это в операционной системе. Stream предоставляет реализацию по умолчанию асинхронных операций чтения и записи на основе синхронных реализаций, а также реализацию по умолчанию синхронных операций чтения и записи на основе асинхронных реализаций.

При реализации класса, производного от Stream, необходимо обеспечить реализацию либо для синхронных, либо для асинхронных методов Read и Write. Хотя переопределение методов Read и Write является допустимым, и по умолчанию реализации асинхронных методов (BeginRead, EndRead, BeginWrite и EndWrite) будут работать с вашей реализацией синхронных методов, это не обеспечивает наиболее высокую производительность. Аналогично, синхронные методы Read и Write также будут работать корректно, если будет предоставлена реализация асинхронных методов. Однако обычно производительность выше, если специально реализовать синхронные методы. По умолчанию реализации ReadByte и WriteByte вызывают синхронные методы Read и Write с одноэлементным массивом байтов. В случае наследования классов от Stream при наличии внутреннего буфера байтов, чтобы получить доступ к внутреннему буферу и тем самым существенно увеличить производительность, рекомендуется переопределять эти методы.

Поток, связанный с резервным хранилищем, переопределяет синхронные или асинхронные методы Read и Write для получения функциональных возможностей других методов по умолчанию. Если поток не поддерживает асинхронные или синхронные операции, то средству реализации необходимо только обеспечить возможность создания исключений соответствующим методом.

Приведенный ниже пример — это асинхронная реализация гипотетического процессора для обработки большого количества образов. Далее приведен пример синхронной реализации. Данный код предназначен для выполнения операций с каждым файлом в каталоге. Эти операции потребляют значительный объем ресурсов процессора. Шаблоны разработки для асинхронного программирования на C#[14].

 

using System; using System.IO; using System.Threading; using System.Runtime.InteropServices; using System.Runtime.Remoting.Messaging; using System.Security.Permissions; public class BulkImageProcAsync{ public const String ImageBaseName = " tmpImage-"; public const int numImages = 200; public const int numPixels = 512 * 512; // ProcessImage has a simple O(N) loop, and you can vary the number // of times you repeat that loop to make the application more CPU- // bound or more IO-bound. public static int processImageRepeats = 20; // Threads must decrement NumImagesToFinish, and protect // their access to it through a mutex. public static int NumImagesToFinish = numImages; public static Object[] NumImagesMutex = new Object[0]; // WaitObject is signalled when all image processing is done. public static Object[] WaitObject = new Object[0]; public class ImageStateObject { public byte[] pixels; public int imageNum; public FileStream fs; } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] public static void MakeImageFiles() { int sides = (int)Math.Sqrt(numPixels); Console.Write(" Making {0} {1}x{1} images... ", numImages, sides); byte[] pixels = new byte[numPixels]; int i; for (i = 0; i < numPixels; i++) pixels[i] = (byte)i; FileStream fs; for (i = 0; i < numImages; i++) { fs = new FileStream(ImageBaseName + i + ".tmp", FileMode.Create, FileAccess.Write, FileShare.None, 8192, false); fs.Write(pixels, 0, pixels.Length); FlushFileBuffers(fs.SafeFileHandle.DangerousGetHandle()); fs.Close(); } fs = null; Console.WriteLine(" Done." ); } public static void ReadInImageCallback(IAsyncResult asyncResult) { ImageStateObject state = (ImageStateObject)asyncResult.AsyncState; Stream stream = state.fs; int bytesRead = stream.EndRead(asyncResult); if (bytesRead! = numPixels) throw new Exception(String.Format (" In ReadInImageCallback, got the wrong number of " + " bytes from the image: {0}.", bytesRead)); ProcessImage(state.pixels, state.imageNum); stream.Close(); // Now write out the image. // Using asynchronous I/O here appears not to be best practice. // It ends up swamping the threadpool, because the threadpool // threads are blocked on I/O requests that were just queued to // the threadpool. FileStream fs = new FileStream(ImageBaseName + state.imageNum + ".done", FileMode.Create, FileAccess.Write, FileShare.None, 4096, false); fs.Write(state.pixels, 0, numPixels); fs.Close(); // This application model uses too much memory. // Releasing memory as soon as possible is a good idea, // especially global state. state.pixels = null; fs = null; // Record that an image is finished now. lock (NumImagesMutex) { NumImagesToFinish--; if (NumImagesToFinish == 0) { Monitor.Enter(WaitObject); Monitor.Pulse(WaitObject); Monitor.Exit(WaitObject); } } } public static void ProcessImage(byte[] pixels, int imageNum) { Console.WriteLine(" ProcessImage {0}", imageNum); int y; // Perform some CPU-intensive operation on the image. for (int x = 0; x < processImageRepeats; x += 1) for (y = 0; y < numPixels; y += 1) pixels[y] += 1; Console.WriteLine(" ProcessImage {0} done.", imageNum); } public static void ProcessImagesInBulk() { Console.WriteLine(" Processing images... " ); long t0 = Environment.TickCount; NumImagesToFinish = numImages; AsyncCallback readImageCallback = new AsyncCallback(ReadInImageCallback); for (int i = 0; i < numImages; i++) { ImageStateObject state = new ImageStateObject(); state.pixels = new byte[numPixels]; state.imageNum = i; // Very large items are read only once, so you can make the // buffer on the FileStream very small to save memory. FileStream fs = new FileStream(ImageBaseName + i + ".tmp", FileMode.Open, FileAccess.Read, FileShare.Read, 1, true); state.fs = fs; fs.BeginRead(state.pixels, 0, numPixels, readImageCallback, state); } // Determine whether all images are done being processed. // If not, block until all are finished. bool mustBlock = false; lock (NumImagesMutex) { if (NumImagesToFinish > 0) mustBlock = true; } if (mustBlock) { Console.WriteLine(" All worker threads are queued. " + " Blocking until they complete. numLeft: {0}", NumImagesToFinish); Monitor.Enter(WaitObject); Monitor.Wait(WaitObject); Monitor.Exit(WaitObject); } long t1 = Environment.TickCount; Console.WriteLine(" Total time processing images: {0}ms", (t1 - t0)); } public static void Cleanup() { for (int i = 0; i < numImages; i++) { File.Delete(ImageBaseName + i + ".tmp" ); File.Delete(ImageBaseName + i + ".done" ); } } public static void TryToClearDiskCache() { // Try to force all pending writes to disk, and clear the // disk cache of any data. byte[] bytes = new byte[100 * (1 < < 20)]; for (int i = 0; i < bytes.Length; i++) bytes[i] = 0; bytes = null; GC.Collect(); Thread.Sleep(2000); } public static void Main(String[] args) { Console.WriteLine(" Bulk image processing sample application, " + " using asynchronous IO" ); Console.WriteLine(" Simulates applying a simple " + " transformation to {0} \" images\" ", numImages); Console.WriteLine(" (Async FileStream & Threadpool benchmark)" ); Console.WriteLine(" Warning - this test requires {0} " + " bytes of temporary space", (numPixels * numImages * 2)); if (args.Length == 1) { processImageRepeats = Int32.Parse(args[0]); Console.WriteLine(" ProcessImage inner loop - {0}.", processImageRepeats); } MakeImageFiles(); TryToClearDiskCache(); ProcessImagesInBulk(); Cleanup(); } [DllImport(" KERNEL32", SetLastError = true)] private static extern void FlushFileBuffers(IntPtr handle); }

Библиография

1. И.Б. Бурдонов, А.С. Косачев, В.Н. Пономаренко Операционные системы реального времени. Препринт Институт системного программирования РАН. - 222 с.

2. С.Зыль. Операционная система реального времени QNX: от теории к практике (2-е издание). СПб.: БХВ-Петербург, 2004. – 192 с.

3. С.Зыль. Проектирование, разработка и анализ программного обеспечения систем реального времени. СПб.: БХВ-Петербург, 2010. – 336 с.

4. Жданов А.А. Операционные системы реального времени. PCWeek. 1999. 8.

5. С.Золотарёв. Операционные системы реального времени для 32-разрядных микропроцессоров. ЗАО " РТСофт", Современная электроника 7/2006 – 8 с.

6. Р.Янг - Языки программирования реального времени. Москва, " Мир", 1986. – 400 с.

7. Ю.Гончаров. Технология eXpress DSP. Статья для журнала “Chip News”

8. http: //prosoft.ru/ - АСУ ТП и встраиваемые системы

9. http: //prosoft.ru/ - С.Сорокин. СРВ.

10.http: //www.lynuxworks.com/

11. http: //msdn.microsoft.com/embedded/

12. http: //www.microware.com/

13. http: //ru.wikipedia.org/


[1] С.Золотарёв. Операционные системы реального времени для 32-разрядных микропроцессоров. ЗАО " РТСофт", Современная электроника 7/2006

 

[2]. С.Зыль. Операционная система реального времени QNX: от теории к практике (2-е издание). СПб.: БХВ-Петербург, 2004. – 192 с..

 

3. И.Б. Бурдонов, А.С. Косачев, В.Н. Пономаренко Операционные системы реального времени..

 

[4] http: //www.lynuxworks.com/

[5] И.Б. Бурдонов, А.С. Косачев, В.Н. Пономаренко Операционные системы реального времени.

 

[6] http: //www.microware.com/

.

 

[7] http: //msdn.microsoft.com/embedded/

[8]. http: //prosoft.ru/ - АСУ ТП и встраиваемые системы.

 

[9] http: //prosoft.ru/ - АСУ ТП и встраиваемые системы.

.

 

[10] http: //prosoft.ru/ - С.Сорокин. СРВ.

.

 

http: //prosoft.ru/ - С.Сорокин. СРВ.

.

[12] http: //prosoft.ru/ - С.Сорокин. СРВ.

 

 

[13]. http: //ru.wikipedia.org/

.

 

[14]. http: //msdn.microsoft.com

 


Поделиться:



Последнее изменение этой страницы: 2017-03-15; Просмотров: 401; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.022 с.)
Главная | Случайная страница | Обратная связь