Как сделать класс Ориентированным на многопотоковое исполнение [закрытый]

Также (в дополнение к Rex и ответам Ian) существует:

imageElement.naturalHeight

и

imageElement.naturalWidth

Они обеспечивают высоту и ширину самого файла изображения (а не просто элемент изображения).

22
задан C. Ross 27 August 2009 в 22:13
поделиться

6 ответов

В C # любой объект может использоваться для защиты «критического раздела», или, другими словами, кода, который не должен выполняться двумя потоками одновременно.

Например, , следующее будет синхронизировать доступ к методу SharedLogger.Write, так что только один поток регистрирует сообщение в любой момент времени.

public class SharedLogger : ILogger
{
   public static SharedLogger Instance = new SharedLogger();

   public void Write(string s)
   {
      lock (_lock)
      {
         _writer.Write(s);
      }
   }

   private SharedLogger() 
   { 
      _writer = new LogWriter();
   }

   private object _lock;
   private LogWriter _writer;
}
19
ответ дан 29 November 2019 в 04:12
поделиться

Я не уверен, что могу добавить что-нибудь к тому, что уже было сказано о том, чтобы сделать класс ведения журнала потокобезопасным. Как уже было сказано, для этого вы должны синхронизировать доступ к ресурсу, то есть к файлу журнала, так, чтобы только один поток пытался войти в него за раз. Ключевое слово C # lock - правильный способ сделать это.

Однако я остановлюсь на (1) одноэлементном подходе и (2) удобстве использования подхода, который вы в конечном итоге решите использовать.

] (1) Если ваше приложение записывает все сообщения журнала в один файл журнала, то одноэлементный шаблон определенно является правильным маршрутом. Файл журнала открывается при запуске и закрывается при завершении работы, и шаблон singleton идеально соответствует этой концепции операций. Однако, как отметил @dtb, помните, что создание класса синглтоном не гарантирует безопасность потоков. Используйте для этого ключевое слово lock .

(2) Что касается удобства использования подхода, рассмотрите это предлагаемое решение:

public class SharedLogger : ILogger
{
   public static SharedLogger Instance = new SharedLogger();
   public void Write(string s)
   {
      lock (_lock)
      {
         _writer.Write(s);
      }
   }
   private SharedLogger()
   {
       _writer = new LogWriter();
   }
   private object _lock;
   private LogWriter _writer;
}

Позвольте мне сначала сказать, что этот подход в целом приемлем. Он определяет одноэлементный экземпляр SharedLogger через статическую переменную Instance и предотвращает создание экземпляра класса другими с помощью частного конструктора. В этом суть синглтона, но я настоятельно рекомендую прочитать и следовать совету Джона Скита относительно синглтонов в C # , прежде чем заходить слишком далеко.

Однако я хочу сосредоточиться на удобстве использования это решение. Под «удобством использования» я имею в виду способ использования этой реализации для регистрации сообщения. Подумайте, как выглядит вызов:

SharedLogger.Instance.Write("log message");

Вся эта часть «Экземпляр» выглядит неправильно, но нет способа избежать этого, учитывая реализацию. Вместо этого рассмотрите эту альтернативу:

public static class SharedLogger : ILogger
{
   private static LogWriter _writer = new LogWriter();
   private static object _lock = new object();
   public static void Write(string s)
   {
       lock (_lock)
       {
           _writer.Write(s);
       }
   }
}

Обратите внимание, что класс теперь статический, а это значит, что все его члены и методы должны быть статическими. Он не отличается существенно от предыдущего примера, но рассмотрите его использование.

SharedLogger.Write("log message");

Это намного проще кодировать.

Дело не в том, чтобы очернить первое решение, а в том, чтобы предположить, что удобство использования любого решения, которое вы выберете, является важный аспект, который нельзя упускать из виду. Хороший, удобный API может упростить написание кода, сделать его более элегантным и легким в поддержке.

рассмотрите эту альтернативу:

public static class SharedLogger : ILogger
{
   private static LogWriter _writer = new LogWriter();
   private static object _lock = new object();
   public static void Write(string s)
   {
       lock (_lock)
       {
           _writer.Write(s);
       }
   }
}

Обратите внимание, что класс теперь статический, а это означает, что все его члены и методы должны быть статическими. Он не отличается существенно от предыдущего примера, но рассмотрите его использование.

SharedLogger.Write("log message");

Это намного проще кодировать.

Дело не в том, чтобы очернить первое решение, а в том, чтобы предположить, что удобство использования любого решения, которое вы выберете, является важный аспект, который нельзя упускать из виду. Хороший, удобный API может упростить написание кода, сделать его более элегантным и легким в поддержке.

рассмотрите эту альтернативу:

public static class SharedLogger : ILogger
{
   private static LogWriter _writer = new LogWriter();
   private static object _lock = new object();
   public static void Write(string s)
   {
       lock (_lock)
       {
           _writer.Write(s);
       }
   }
}

Обратите внимание, что класс теперь статический, а это значит, что все его члены и методы должны быть статическими. Он не отличается существенно от предыдущего примера, но рассмотрите его использование.

SharedLogger.Write("log message");

Это намного проще кодировать.

Дело не в том, чтобы очернить первое решение, а в том, чтобы предположить, что удобство использования любого решения, которое вы выберете, является важный аспект, который нельзя упускать из виду. Хороший, удобный API может упростить написание кода, сделать его более элегантным и легким в поддержке.

но предположить, что удобство использования любого выбранного вами решения - важный аспект, который нельзя упускать из виду. Хороший, удобный API может упростить написание кода, сделать его более элегантным и легким в поддержке.

но предположить, что удобство использования любого выбранного вами решения - важный аспект, который нельзя упускать из виду. Хороший, удобный API может упростить написание кода, сделать его более элегантным и легким в поддержке.

11
ответ дан 29 November 2019 в 04:12
поделиться
  • Попробуйте выполнить большую часть вычислений с использованием локальных переменных, а затем измените состояние объекта в одном быстром блоке lock ed.
  • Имейте в виду, что некоторые переменные могут изменяться между тем, когда вы их читаете, и когда вы их получаете к изменению состояния.
6
ответ дан 29 November 2019 в 04:12
поделиться

Согласно ответу BCS:

BCS описывает случай объекта без состояния. Такой объект по своей сути является потокобезопасным, потому что он не имеет собственных переменных, которые могут быть заторможены вызовами из разных theads.

Описанный регистратор имеет дескриптор файла (извините, не пользователь C #, возможно, он называется IDiskFileResource или что-то в этом роде MS-ism), использование которого должно быть сериализовано.

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

Один из способов сделать это: если объект регистратора должен был хранить очередь объектов сообщений, а объект регистратора просто имеет логику для выталкивания сообщения из очереди , затем извлеките полезный материал из объекта сообщения, затем запишите это в журнал, затем найдите другое сообщение в очереди - тогда вы можете сделать этот поток безопасным, сделав потокобезопасными операции add / remove / queue_size / etc очереди. Для этого потребуется класс регистратора, класс сообщений и потокобезопасная очередь (которая, вероятно, является третьим классом, экземпляр которого является переменной-членом класса регистратора).

2
ответ дан 29 November 2019 в 04:12
поделиться

используйте lock () , чтобы несколько потоков не использовали ведение журнала одновременно

3
ответ дан 29 November 2019 в 04:12
поделиться

Я бы использовал для этого стандартный регистратор, так как есть несколько, которые надежны и просты в использовании. Не нужно катать самостоятельно. Я рекомендую Log4Net.

8
ответ дан 29 November 2019 в 04:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: