Спасибо. Честно говоря, не замерял накладные расходы, т.к. этот код написан исключительно для ответа на вопрос. А что именно может повлиять на производительность?
simply_user: всё правильно, можно и так, как вы написали (переменную tmp можно убрать и писать return прямо внутри lock). Но я считаю, в вашем случае ввод разных объектов - это преждевременная оптимизация, которая только усложняет читаемость, но даёт, скорее всего, минимальный прирост производительности. Если уж вы не хотите использовать volatile, я бы посоветовал просто пометить все методы класса атрибутом [MethodImpl(Synchronized)]. Это то же самое, что lock с общим объектом синхронизации, только объектом в данном случае будет являться сам класс.
Так работать не будет. Вы на каждое чтение и запись создаёте новый объект синхронизации, а идея блокировок как раз в том, чтобы объект синхронизации был один. Либо по одному объекту на каждое поле класса, чтобы можно было менять (или читать) разные поля одновременно из нескольких потоков, что, похоже, не ваш случай - у вас всего два потока - один меняет, другой читает. Поэтому можно синхронизироваться на одном объекте. Вам нужно один раз создать статическое поле "private static object lockObj = new object();" внутри класса и использовать его во всех методах. Но вообще говоря, как я уже сказал, в вашем случае можно вообще обойтись без блокировок и использовать volatile.
Кстати, вы неправильно используете Monitor. Правильно - так:
try
{
Monitor.Enter(lockObj);
...
}
finally
{
Monitor.Exit(lockObj);
}
А еще лучше - использовать ключевое слово lock - это на самом деле синтаксический сахар над Monitor-ом, который как раз и делает то, что я написал выше.
Алексей Немиро: Регулярные выражения проигрывают потому, что основное время уходит на парсинг шаблона. По хорошему, стопвотч нужно запускать после создания Regex-инстанса, а затем в цикле прогнать тест раз миллион. Тогда можно судить о среднем времени выполнения.
Сорри, не заметил комментариев к предыдущему ответу. :) Но что-то мне подсказывает, что ошибка на самом деле не в том месте, где вы указали. Вероятно, данный цикл выполняется в callback-е какого-то web request-а, на потоке ThreadPool-а или еще где-то. Но в цикле вы каким-то образом взаимодействуете с UI. В этом случае, как я и сказал, поможет Dispatcher.Invoke/BeginInvoke. Но вообще, это гадание на кофейной гуще :)
Про нагрузку в Thread.Sleep можно поподробнее? На самом деле, подход с Thread.Sleep тоже имеет право на жизнь, только его нужно слегка "подтюнить", вычитая из задержки время выполнения предыдущего callback-а. Более того, иногда этот метод работает гораздо точнее таймера, т.к. таймер использует ThreadPool, который при нерациональном использовании, в следствие своей singleton-ной природы, может забиться задачами из других частей программы. Я сам сталкивался с проблемой отставаний таймеров, которые доходили до нескольких секунд в одной очень критической к задержкам функциональности. Перешли на NewThreadScheduler из Reactive Extensions - проблема исчезла. Главное - не забывать, что количество потоков всегда следует минимизировать, поэтому чаще всего таймеры - действительно оптимальный вариант.
Погорячился с тоном комментария, извините. И всё же, предобработка в данном случае имеет ту же сложность O(n), да и не понятно, в чём она должна заключаться? Даже если заменить все нулевые символы на что-то другое, нет никакой гарантии, что строка будет заканчиваться нулём. Видимо, из-за этого ваш код падает у @aush.
А теперь попробуйте подать на вход эдак 20-мегабайтный файл, состоящий исключительно из символов '\n'.
Советую не изобретать велосипед и использовать result = result.Replace("\n", "");
Либо
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
char c = input[i];
if (c != '\n')
{
sb.Append(c);
}
}
result = sb.ToString();
Это вообще что за код такой? В C# никогда не использовались null-terminated strings. Ваш код не будет работать со строками, содержащими нулевые символы. А использовать unsafe-код без необходимости - дурной тон.
@ekdown Можно, конечно, но не универсально. В настройках ОС можно поставить любой символ-разделитель для дроби. Мало кому придет в голову использовать что-то кроме точки и запятой, но тем не менее.
WCF как раз и использует shared memory для межпроцессного взаимодействия, если не ошибаюсь. Я же не говорил, что необходимо напрямую работать с WinAPI-функциями. Можно использовать WCF, можно System.IO.MemoryMappedFiles, тут уж решать автору вопроса. Ну и да, сокеты тоже вариант, но, имхо, избыточный.
Да это-то можно, не спорю. Просто на мой взгляд, с несколькими Where код получается нагляднее. А Linq2Sql-транслятору пофиг как код будет записан. Он и то, и то одинаково оттранслирует.