Сегодня: Пятница, 19.04.2024, 05:26 (МСК)| Здравствуйте, Гость| Мой профиль | Регистрация | Вход | RSS

Популярно об ИИ.
Третий сезон

Моделирование в Maxon Cinema4D

Эргономика компьютерных клавиатур

ТВ-тюнеры. Как выбирать?

Плагины Sonnox Oxford
Главная » ПРОГРАММИРОВАНИЕ

Ответы на письма. Вопросы по C#

03.01.2012

Вопросов на e-mail приходит много… довольно большая их часть касается темы программирования. В рамках этого небольшого материала я отвечу на те письма, которые сохранял и складировал в своей папке «Вопросы по C#»… за последние два месяца. Хотя последний ответ в данной подборке я взял из своих старых подборок вопрос-ответов, потому как отвечать много раз на одно и то же не хотелось.

Итак, поехали, читаем первое письмо:


***


«Вы написали отличный материал по компиляторам и бесплатным IDE для языков C и C++, а есть ли что-нибудь подобное и бесплатное, чем можно заменить Microsoft Visual C#? В интернете нашел ссылку на Mono (http://mono-project.com/), но так ничего и не смог понять, как с ним работать. Надеюсь на Ваш скорый ответ.
С уважением,
Андрей»

Вы немного запутались, что, в принципе, среди open source продуктов сделать довольно просто:). Mono (на который вы дали ссылку), является развитым кроссплатформенным проектом на базе бесплатного ПО, заменяющим программную платформу .NET Framework. То есть, это компиляторы, отладчики и так далее. К нему могут привязываться графические библиотеки элементов интерфейса GTK+, wxWidgets (а точнее разновидность wx.NET). То есть, Mono следует рассматривать как бесплатную альтернативу .NET. Mono актуален большей частью для создания  кроссплатформенных приложений.

Если же вы хотите непосредственно программировать как в Visual Studio, то вам понадобится среда разработки и проектирования, и первое, что вам предложат — это MonoDevelop (http://monodevelop.com/). Скорее всего именно с ней вы и спутали проект Mono. Но (!) при этом, например, при установке Windows-варианта этой IDE в качестве базовой основы (компиляторы и т.п.) вам предложат не Mono, а .NET Framework от Microsoft, а также специальную адаптацию GTK+ — GTK # для .NET.  

В принципе, этот вариант не намного сильнее предлагаемого Microsoft’ом бесплатного Visual C# Express.

Лично я, если стоит задача создания .NET-приложений с требованиями по использованию бесплатного ПО разработки, использую другую IDE, а именно SharpDevelop или как ее называют часто #develop (http://www.icsharpcode.net). По функциональности интерфейса она очень близка к Visual C# для Microsoft. Причем стоит отметить, что упомянутая выше MonoDevelop в одно время было простым ответвлением SharpDevelop, а точнее, SharpDevelop на Mono/GTK+. Теперь это различные IDE. 

Но, в принципе, если говорить, например, о C и C++, то бесплатные компиляторы и IDE являются вполне конкурентоспособными, а иногда даже и более выигрывающими по сравнению с брендовыми и коммерческими. Про C# так сказать нельзя, потому как язык в значительной мере заточен под технологии Microsoft.  


***


Идем дальше. Читаю следующее письмо…:) Ну, вот, кто так на C# пишет код: string stroka1 = TextBox1.Text.ToString()? Как говорится: «аффтар жжот плюсадин». Для тех, кто не понял, разъясню: TextBox1.Text — это уже значение строчного типа string. Хотя, в принципе, это можно списать на так называемое «замыливание» взгляда, поскольку множество компонент требуют приведения типов. 

А вопрос касается… замены символов в строке, в которую загружен большой объем текста. Я думаю, что написавший уже и сам нашел ответ пока дожидался моего. В принципе, все просто, — в стандартном варианте это делается с помощью метода Replace класса String, хотя, если речь идет не об очень больших текстах, я обычно использую более быстрый Replace от класса String Builder, у него другая структура работы. Читайте MSDN. Для рабочего примера, давайте реализуем функцию, которая бы правильно расставляла пробелы вокруг двоеточий в любом приходящем тексте:

static string EditFunc(string p)
{
    StringBuilder b = new StringBuilder(p);
    b.Replace(" :", ":");
    b.Replace(":", ": ");
    b.Replace("  ", " ");
    return b.ToString();
}


***

Следующее письмо интересно, хотя сам код автора не привожу, поскольку он большой:

Помогите, пожалуйста, я делаю программу, работающую с базой данных. Как обойти DBConcurrencyException — исключение, которое вызывается DataAdapter при операции вставки, обновления или удаления не затронувшей ни одной строки. Посмотрите код, в чем ошибка? Там DataAdapter помещен в lock(), как мне посоветовали, это не помогло, и нужно ли вообще использовать lock()?

М-да, ну, lock() — это, конечно, всегда хорошо. Например, когда я пишу серьезное приложение на C#, то наиболее часто встречаемыми конструкциями в моем коде являются try — catch и lock() (или подобные решения).

Теперь по вашему коду. Во-первых, главная ошибка всех начинающих, работающих с DataGridView и пытающимся изменить содержимое БД программно. Дело в том, что элемент DataGridView только отображает данные таблицы DataTable. Чтобы внести изменения в отображение, вы должны вносить изменения в DataTable. Поэтому программным присваиванием… 

dataGridView1.Rows[i].Cells[18].Value = baseId [i]; 

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

((DataTable)dataGridView1.DataSource).Rows[i][18] = baseId [i];

После делаете Update объекта DataAdapter. Многие путаются в этом вопросе по той причине, что если изменения вносятся вручную пользователем на объекте DataGridView, они вносятся в DataTable и обновления происходят успешно. Но программно ситуацию нужно решать по-другому. 

DBConcurrencyException в большинстве случаев возникает из-за нарушения параллелизма, когда изменения вносятся до фактического обновления объекта DataTable. 

При этом DataAdapter после генерации исключения останавливает свою работу и появляется соответствующая ошибка. Обойти это можно, задав свойство DataAdapter. ContinueUpdateDnError как true (по умолчанию оно является false). Затем можно просканировать ошибки в DataTable.HasErrors (см. справочную информацию по нему).
Переходим к следующему вопросу, и он опять… об ошибке…


***


Кристофер, не могу понять, в чем дело, сканю Excel-базы и связанные с ними Word-файлы, все проходит с треском, но идет, добавляю вызов функции сверки текста, выскакивает 
«ContextSwitchDeadlock was detected
Message: The CLR has been unable to transition from COM context 0x159bc0 to COM context 0x1598e0 for 60 seconds…»
У меня вхождения в бесконечный цикл нет, я проверял, таймеры также не использую. Как решить проблему?
Жду скорого ответа!

Эту ошибку часто именуют ошибкой длительных процессов. Если говорить простыми словами, в данном случае отладчик предполагает, что у вас есть некий неправильный процесс, опираясь на то, как программа себя ведет. В принципе, в большинстве случаев я встречал этот вариант при работе с Excel-файлами:), хотя варианты бывали различными. В вашем случае я бы рекомендовал «как можно меньше Excel’а», например, загрузив его через OleDb в DataGridView, после чего оперируя только данными из этого визуального представления (а не перелопачивая файл), во-вторых, я бы порекомендовал более грамотно обращаться  с потоками, например, содержать как можно меньше вычислений в основном рабочем потоке, это же относится и к визуальным компонентам, которые отображают процессы. 

Ну, и если вы во всем уверены, что все работает правильно ContextSwitchDeadlock можно просто отключить в отладчике Debug->Exceptions->Managed Debug Assistants (отключаем птичку напротив ContextSwitchDeadlock).


***


«Тестируем игровое приложение… основной код на C#... иногда появляются просто глюки…».

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

В самом простом случае синхронизация доступа осуществляется за счет использования оператора lock(а в скобках указывается маркер), т.е. см. документацию по этому поводу. При этом lock является сокращенным вариантом типа класса System.Threading.Monitor, используя который вы получите чуть большую степень управления по сравнению с первым из предложенного, хотя и более громоздкую. Также можно задействовать для синхронизации класс System.Threading.Interlocked, что будет эргономичнее для программирования. Помимо этого есть и еще один вариант, а именно, атрибут [Synchronization] определенный в пространстве имен System.Runtime.Remoting.Contexts. То есть, тут все на ваше усмотрение. Думается, что четырех вариантов хватит, хотя их может быть гораздо больше, важна также и специфика выполняемых в рамках этих потоков задач. 


Кристофер

Перепечатка материалов или их фрагментов возможна только с согласия автора







Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Ассоциация боевых роботов
Рекомендуем...
Новости

Разделы

Опросы

Какой язык программирования вы считаете наиболее актуальным сегодня?
Всего ответов: 329

Друзья

3D-кино






Найти на сайте:








Об авторе       Контакты      Вопрос-ответ        Хостинг от uCoz