понедельник, 17 сентября 2007 г.

Параллельное выполнение кода в .Net Framework 3.5

Вы не ждали? А мы пришли!

Э... О чем это я?

А!

Microsoft разрабатывает библиотеку для упрощения процесса написания программ, в которых отдельные элементы алгоритма можно выполнять параллельно. Более подробно (на русском!) об этой библиотеке можно почитать здесь

Последнее время все чаще встречаю статьи о том, что "несколько ядер/процессоров это конечно хорошо... но вот программировать под них...". Так вот, теперь это не просто, теперь это очень просто! :)

P.S.: а С++ пора начинать забывать. Как страшный сон.

суббота, 15 сентября 2007 г.

Полезный ListView

Совершенно случайно нашел то, что давно искал, а именно - модифицированный ListView, который позволяет группировать элементы. Да-да, я знаю, что стандартный ListView это тоже умеет, однако делает он это очень плохо. Контрол можно найти тут: http://www.codeproject.com/cs/miscctrl/outlooklistcontrol.asp Выглядит он вот так: Самое интересное, что возможностей у него очень и очень много. Кроме того, можно переопределять стандартную отрисовку любой части контрола, причем для этого даже не надо лезть и что-то исправлять в его исходном коде! Хотя нет. Вру :) Мне все-таки пришлось кое-что подправить. Видите воон ту желтую область слева? Вот ее-то и пришлось править - цвет области был жестко зашит в коде. Вообщем, теперь у меня это выглядит вот так (в моем втором более-менее крупном проекте MusicSorter):

воскресенье, 9 сентября 2007 г.

Новый движок для скриптов готов!

    Сегодня великий день :) Я окончательно доделал новый движок скриптов (скрипты даже компилируются и работают в основной программе-переводчике!). Теперь скрипты пишутся исключительно на на языке C#. Применяться он будет в составе алгоритма синтаксического анализа предложений вместо уже существующего.

    Наверное стоит рассказать, чем же меня не устраивала предыдущая версия. Пожалуй самая основная ее проблема в том, что предыдущий движок был декларативным. Фактически, любое правило описывало жестко заданный алгоритм: 

  1. поиск слов имеющих заданные параметры и замена в строке-представлении предложения символа в соответствующей позиции (равной номеру слова в предложении) на заданный симво
  2. поиск в предложении участка по заданному регулярному выражению
  3. если поиск увенчался успехом, то производятся заданные действия - например, установка у указанных слов определенных параметров, добавление связей между словами и т.п.

где разработчик правила мог указывать необходимый (и строго фиксированный!) набор параметров.

    Фактически я получил более-менее гибкую систему главной особенностью которой было то. что она полностью управлялась набором параметров (параметры описываются специальным классом). В результате - мало того, что на каждый новый параметр надо было писать отдельный алгоритм обработки, так еще и из-за того что данные параметры являются глобальными (и используются практически во всех частях переводчика), то о каком либо расширении набора параметров или изменении логики их обработки сторонними разработчиками можно было смело забыть.

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

На данный момент запланированы следующие задачи:

  1. реализовать поддержку нескольких библиотек скриптов в редакторе с соответствующей компиляцией в разные .dll
  2. сконвертировать все старые скрипты к новому виду - т.е. фактически написать алгоритм генерации класса по описанию правила.
  3. разработать набор визардов для автоматической генерации простых скриптов (лень - двигатель прогресса!)

    Ну и как не похвалиться? На скриншоте можно посмотреть структуру стандартного скрипта:

    Функция Init используется для инициализации. Там необходимо выполнять те действия, которые можно сделать один раз и потом пользоваться результатом В частности я предполагаю выполнять там действия по инициализации алгоритма поиска.

    Ну и самая главная функция - Run - которая вызывается в цикле до тех пор пока возвращает true (ну о том, как именно работает алгоритм анализа я расскажу по-позже).

четверг, 6 сентября 2007 г.

Nullable типы в C#

Разбираясь с примером по WWF наткнулся на странное объявление переменной. Выглядело это примерно так:

int? i;

Недолгие поиски в гугле привели меня на сайт MSDN.

Как оказалось - такие типы имеют еще одно значение - null, показывающее, что значение не установлено. Сделано это, в основном, для совместимости с логикой работы с типами в базах данных.

Как это работает.

Объявленный таким способом тип имеет помимо прочих еще два члена:

  • HasValue - показывает, не записано ли null в Value
  • Value - содержит само значение переменной нашего типа

В случае, если данные в переменную не записаны (т.е. фактически она равна null), то при попытке как-то взаимодействовать с такой переменной мы получаем InvalidOperationException. Если данные записаны - то все работает так же как и у переменных обычного типа.

Примеры:


int? x = 10;
if (x.HasValue)
    System.Console.WriteLine(x.Value);
else
    System.Console.WriteLine("Undefined");

int? y = 10;
if (y != null)
    System.Console.WriteLine(y.Value);
else
    System.Console.WriteLine("Undefined");

понедельник, 3 сентября 2007 г.

Xml-сериализация сложных коллекций

Ну я надеюсь что про простую xml-сериализацию вы уже знаете :) Однако постоянно встает вопрос - как сериализовать классы, содержащие коллекции типа Hastable, Dictionary или Hashset (новый тип, доступный в 3-ей версии .Net Framework). Итак. Первое что нам понадобится:
using System.Runtime.Serialization; 
Второе. Пометить сериализуемые классы (все! включая вложенные!) атрибутом [DataContract] и все члены класса, данные которых надо сериализовать артибутом [DataMember]:
[DataContract]
public class MySerializableClass
{
   [DataMember]
   public Dictionary MyCollection = new Dictionary();
   ...
}
Сериализация производится следующим образом:

public void SaveData(string path, MySerializableClass msc)
{
   XmlTextWriter xw = new XmlTextWriter(path, Encoding.UTF8);
   //а это чтобы красиво было :)
   xw.Formatting = Formatting.Indented;
   XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(xw);
   DataContractSerializer ser = new DataContractSerializer(typeof(MySerializableClass));
   ser.WriteObject(writer, ds);
   writer.Close();
   xw.Close();
}
Ну и, соответственно, десериализация:

public MySerializableClass LoadData(string path)
{
   MySerializableClass msc = null;   using (FileStream fs = new FileStream(path, FileMode.Open))
   {
      XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, Encoding.UTF8, new XmlDictionaryReaderQuotas(), null);
      DataContractSerializer ser = new DataContractSerializer(typeof(MySerializableClass));
      msc = (MySerializableClass)ser.ReadObject(reader);
   }

   return msc;
}
P.S.: ну естественно, что все красоты с использованием отступов и кодировок можно опустить - но наша же цель состоит именно в том, чтобы получить более-менее читаемый файл...