Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/40: Рейтинг темы: голосов - 40, средняя оценка - 4.80
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163

Семафоры. Синхронизация доступа к файлу

08.07.2012, 18:33. Показов 7585. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
здравствуйте господа программисты. Пишу HTTP сервер, задача такая: необходимо записывать в лог файл некую информацию о подключенных клиентах. лог файл один, а в секунду к серверу может быть сколь угодно много подключений, стало быть просто писать в этот файл не вариант. Сервер многопоточный, каждый клиент передается в новый поток с использованием пула потоков. Для записи в лог хочу использовать семафор, но как правильно реализовать его не знаю. Помогите пожалуйста, может кто сталкивался с такой проблемой.

Код сервера:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
 
namespace HTTPServer
{
    
    // Класс-обработчик клиента
    class Client
    {
 
        // Конструктор класса. Ему нужно передавать принятого клиента от TcpListener
        public Client(Socket cl)
        {
            this.myClient = cl;
 
            //выводим данные на консоль
            string str = getClientMessages();
            if (str == null || str == "")
            {
                this.myClient.Shutdown(SocketShutdown.Both);
                this.myClient.Close();
            }
            else
            {
                Console.WriteLine("Сlient Message : {0}", str);
                SendMessage("Все нормально");
            }
        }
        
        
        private Socket _myCl = null;
        
        private Socket myClient
        {
            get { return  _myCl; }
            set { _myCl = value; }
        }
 
        private void SendMessage(string str)
        {/*
            byte[] Buffer = Encoding.Unicode.GetBytes("Лови ответ");
            // Отправим его клиенту
            myClient.GetStream().Write(Buffer, 0, Buffer.Length);
            myClient.Close();*/
            byte[] msg = Encoding.Unicode.GetBytes(str);
            this.myClient.Send(msg);
        }
 
        private string getClientMessages()
        {
            byte[] bytes = new byte[1024];
            
            //дождались клиента,пытающегося с нами соединиться  
            int bytesRec = this.myClient.Receive(bytes);
            string data = null;
            data += Encoding.Unicode.GetString(bytes, 0, bytesRec);       
            /*
            // Объявим строку, в которой будет хранится запрос клиента
            string Request = null;
            
            // Буфер для хранения принятых от клиента данных
            byte[] Buffer = new byte[1024];
            // Переменная для хранения количества байт, принятых от клиента
            
            int Count;
            Count = myClient.GetStream().Read(Buffer, 0, Buffer.Length);
 
            if (Count > 0)
            {
                Request = Encoding.Unicode.GetString(Buffer, 0, Count);
            }*/
 
            return data;
              
        }
        
    }
 
    class Server
    {
       
        private static TcpListener Listener; // Объект, принимающий TCP-клиентов
        byte[] bytes = new byte[1024];
 
        IPHostEntry ipHost;
        IPAddress ipAddr;
        IPEndPoint ipEndPoint;
        Socket sListener;
 
        private int _port = 0;
        public int port
        {
            get { return _port; }
            //set { _port = value; }
        }
 
        // инициализируем все необходимое для работы нашего сервиса
        public Server(int port)
        {
            //Устанавливаем для сокета локальную конечную точку
            ipHost = Dns.Resolve("localhost");
            ipAddr = ipHost.AddressList[0];
            ipEndPoint = new IPEndPoint(ipAddr, 80);
            sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            
            _port = port;
            //Listener = new TcpListener(IPAddress.Any, _port); // Создаем "слушателя" для указанного порта
            //Listener.Start(); // Запускаем его
 
        }
        
        // этот метод выполняется в отдельом потоке
        public void Start()
        {
            sListener.Bind(ipEndPoint);
            sListener.Listen(10); 
            // В бесконечном цикле
            while (true)
            {
 
                //Начинаем слущать соединения 
                // Принимаем новых клиентов. После того, как клиент был принят, он передается в новый поток (ClientThread)
                // с использованием пула потоков.
                //Socket handler = sListener.Accept();
                ThreadPool.QueueUserWorkItem(new WaitCallback(ClientThread), sListener.Accept());
 
                /*
                // Принимаем нового клиента
                TcpClient Client = Listener.AcceptTcpClient();
                // Создаем поток
                Thread Thread = new Thread(new ParameterizedThreadStart(ClientThread));
                // И запускаем этот поток, передавая ему принятого клиента
                Thread.Start(Client);
                */
            }       
        }
 
        static void ClientThread(Object StateInfo)
        {
            // Просто создаем новый экземпляр класса Client и передаем ему приведенный к классу TcpClient объект StateInfo
            new Client((Socket)StateInfo);
        }
 
            
        // Остановка сервера
        ~Server()
        {
            // Если "слушатель" был создан
            if (Listener != null)
            {
                // Остановим его
                Listener.Stop();
            }
 
            if (sListener != null)
            {
                sListener.Shutdown(SocketShutdown.Both);
                sListener.Close();
            }
        }
 
        static void Main(string[] args)
        {
            // Определим нужное максимальное количество потоков
            // Пусть будет по 4 на каждый процессор
            int MaxThreadsCount = Environment.ProcessorCount * 4;
            // Установим максимальное количество рабочих потоков
            ThreadPool.SetMaxThreads(MaxThreadsCount, MaxThreadsCount);
            // Установим минимальное количество рабочих потоков
            ThreadPool.SetMinThreads(2, 2);
            
            // Создадим новый сервер на порту 80
            Server srv = new Server(80);
            // Создадим поток для нашего сервера
            Thread servis_thread = new Thread(new ThreadStart(srv.Start));
            // запускаем сервер в новом потоке
            servis_thread.Start();
 
 
        }
    }
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.07.2012, 18:33
Ответы с готовыми решениями:

Синхронизация используя семафоры или мьютексы
Добрый день, добрые люди подскажите у меня есть 4 потока и в них выполняеться вычеление функции A= (B+C)*(MC*MD), и мне нужно все 4 потока...

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

Синхронизация доступа к общим данным
Вечер добрый, товарищи. Возникло три вопроса. Первый. Возможно ли создать массив byte с более чем 2 млн. элементов. ...

20
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.07.2012, 20:07
Семафор - не лучший метод синхронизации в вашем случае.
Так как файловый поток является эксклюзивным ресурсом, здесь можно обойтись обычным замыканием через класс Monitor, он же блок lock
C#
1
lock (syncRoot) file.WriteLine("blabla");
Где syncRoot - объект для синхронизации, а file - экземпляр FileStream.
0
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163
08.07.2012, 20:29  [ТС]
сам прихожу к этому выводу, lock походу работает быстрее

Добавлено через 3 минуты
C#
1
ThreadPool.QueueUserWorkItem(new WaitCallback(ClientThread), sListener.Accept());
а вот мы создали новый поток для текущего клиента, далее он отправил ответ клиенту обратно
C#
1
2
3
4
5
6
7
8
9
        private void SendMessage(string str)
        {/*
            byte[] Buffer = Encoding.Unicode.GetBytes("Лови ответ");
            // Отправим его клиенту
            myClient.GetStream().Write(Buffer, 0, Buffer.Length);
            myClient.Close();*/
            byte[] msg = Encoding.Unicode.GetBytes(str);
            this.myClient.Send(msg);
        }
следующая проблема:
теперь как уничтожить этот поток??? он так и останится висеть в памяти??? так ведь и памяти может не хватить хд )))
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.07.2012, 23:01
Поток схлапывается по заврешении метода.
В случае использования пула, потоки не схлапываются, а отдаются "на растерзание" следующему методу в очереди - повышает производительность.

И да, семафор медленнее монитора (1 микросекунда против 100 наносекунд). В четверке, правда, добавили класс SemaphoreSlim, замыкание которого занимает в районе 250 наносекунд.
1
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163
09.07.2012, 08:49  [ТС]
на какой строчке уничтожается поток в приведенном примере??? покажите пожалуйста сам метод и строку на которой поток уже не существует. )
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.07.2012, 10:52
Ilnur888, не работал с потоками в шарпе, но если они IDisposable, то мб стоит воспользоваться using (...)?
0
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163
09.07.2012, 10:57  [ТС]
если честно я вас не понял...
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.07.2012, 11:03
Ilnur888,
C#
1
2
3
4
5
using (streamreader sr = new StreamReader(new FileStream("abc.txt",FileMode.Open)))
{
   string s = sr.ReadToEnd;
   ...
}
к примеру, тут есть объект IDispossible, он автоматически удаляется.
0
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163
09.07.2012, 11:45  [ТС]
я хочу понять где именно завершает работу текущий поток потому что у меня проблемы с синхронизацией потоков при записи в файл. как я понял один процесс может обслуживать N потоков. который мы установили
C#
1
2
3
4
5
            // Определим нужное максимальное количество потоков
            // Пусть будет по 4 на каждый процессор
            int MaxThreadsCount = Environment.ProcessorCount * 4;
            // Установим максимальное количество рабочих потоков
            ThreadPool.SetMaxThreads(MaxThreadsCount, MaxThreadsCount);
но, если число потоков превышает N то вылетает исключение "якобы процесс не может получить доступ к файлу", стало быть мне необходимо еще и синхронизировать потоки что ли??? (это первый вопрос) из него же следствие ведь если потоки сами уничтожаются то внутри процесса для нового потока должно освободиться место и он не должен ругаться на процесс, я правильно понимаю принцип работы этого механизма или нет???

Добавлено через 1 минуту
извиняюсь синхронизировать процессы, в первом вопросе )

Добавлено через 38 минут
подскажите пожалуйста где я допустил ошибку при синхронизации потоков при записи в файл???
метод реализующий запись в файл:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
public void Read_Of_Log()
        {
            lock (_SyncObject)
            {
 
                StreamWriter sFile;
                FileInfo myFile = new FileInfo(_file_patch);
                sFile = myFile.AppendText();
                sFile.WriteLine("  ==>  " + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss"));
                sFile.Close();
 
            }
        }
код всего класса:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    // Класс-обработчик клиента
    class Client
    {
        private string _file_patch = new FileInfo(@System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + @"\data\MyFirstService.log";
 
        private object _SyncObject = new object();  
 
        public void Read_Of_Log()
        {
            lock (_SyncObject)
            {
 
                StreamWriter sFile;
                FileInfo myFile = new FileInfo(_file_patch);
                sFile = myFile.AppendText();
                sFile.WriteLine("  ==>  " + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss"));
                sFile.Close();
 
            }
        }
 
        // Конструктор класса. Ему нужно передавать принятого клиента от TcpListener
        public Client(Socket cl)
        {
            this.myClient = cl;
         
            //выводим данные на консоль
            string str = getClientMessages();
            if (str != null && str != "")
            {
                // выводим то что мы получили
                Console.WriteLine("Сlient Message : {0}", str);
                // отправляем ответ назад отправителю
                SendMessage("Все нормально");
            }
            this.myClient.Shutdown(SocketShutdown.Both);
            this.myClient.Close();
        }
 
        ~Client()
        {
            //this.myClient.Shutdown(SocketShutdown.Both);
            //this.myClient.Close();
        }
        
        
        private Socket _myCl = null;
        
        private Socket myClient
        {
            get { return  _myCl; }
            set { _myCl = value; }
        }
 
        private void SendMessage(string str)
        {
            try
            {
                byte[] msg = Encoding.Unicode.GetBytes(str);
                this.myClient.Send(msg);
            }
            catch
            {
 
            }
        }
 
        private string getClientMessages()
        {
            try
            {
                byte[] bytes = new byte[1024];
 
                //дождались клиента,пытающегося с нами соединиться
                int bytesRec = this.myClient.Receive(bytes);
                string data = null;
                data += Encoding.Unicode.GetString(bytes, 0, bytesRec);
 
                return data;
            }
            catch (Exception e)
            {
                return e.Message;
            }
              
        }
        
    }
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.07.2012, 12:00
Ilnur888, ну я так понимаю, просто происходит просто гонка за ресурс (файл). Просто в данном случае нужно настраивать работу критических секций, я так думаю.
http://ru.wikipedia.org/wiki/%... 0%B8%D1%8F
0
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163
09.07.2012, 12:11  [ТС]
блин но код записи в файл находится в секции look это в свою очередь гарантирует то, что код в этой секции в данный момент времени может быть занят только одним потоком
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        private object _SyncObject = new object();
 
        public void Read_Of_Log(string path)
        {
            lock (_SyncObject)
            {
 
                StreamWriter sFile;
                FileInfo myFile = new FileInfo(path);
                sFile = myFile.AppendText();
                sFile.WriteLine("  ==>  " + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss"));
                sFile.Close();
 
            }
        }
исключение возникает на этой строчке:
C#
1
sFile = myFile.AppendText();
говорит что файл занят другим процессом (((
как то же можно решить эту проблему ???
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
09.07.2012, 13:48
Цитата Сообщение от Ilnur888 Посмотреть сообщение
на какой строчке уничтожается поток в приведенном примере?
Я ж написал: поток завершает свою работу по завершении метода, переданного в этот поток. То есть сразу же после последней закрывающей скобки, строчка номер 9.

Цитата Сообщение от Ilnur888 Посмотреть сообщение
стало быть мне необходимо еще и синхронизировать процессы что ли?
Если два процесса хотят получить доступ к одному и тому же файлу, то разумеется их надо тоже синхронизировать.

Цитата Сообщение от Ilnur888 Посмотреть сообщение
где я допустил ошибку при синхронизации потоков при записи в файл?
С самой синхронизацией ошибки нет (за исключением возможностей для оптимизации критической зоны).
Если у вас вылетает исключение о занятом файле, то какой-то из потоков либо не синхронизирован, либо другой процесс пытается обратиться к этому же файлу.
В случае двух процессов, обращающихся к одному и тому же файлу (клиент и сервер, например), вам нужно будет синхронизировать эти процессы - тут уже монитором не отделаться, придется использовать те же расшаренные семафоры или (лучший вариант в данном случае) использовать класс Mutex, который позволяет производить синхронизацию между процессами:

C#
1
2
3
4
5
using (var mutex = new Mutex(true, "SharedMutexName"))
{
   mutex.WaitOne(); // Заморозить поток, пока другой поток или процесс используют данный мьютекс
   ...
}
0
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163
10.07.2012, 14:15  [ТС]
Столкнулся с ещё одной проблемой (. Необходимо сделать кэш таблицы базы данных, и так чтобы этот кэш был общедоступным для каждого клиента, который запущен каждый в отдельном потоке. Если кто сталкивался с такой проблемой подскажите пожалуйста в каком направлении копать???
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
10.07.2012, 14:25
Ilnur888, сделать статическое свойство кэша, и lock его для записи, для чтения можно оставить параллельное считывание (если никаких ошибок не вылезет с одновременным доступом)
1
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163
10.07.2012, 17:05  [ТС]
столкнулся с такой проблемой, вобщем есть код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
                // создаем новый лист
                lst = new List<Nomenclature>();
 
                // открываем созданное нами подключение
                con.Open();
 
                // заполняем наш массив данными
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
 
                        lst.Add(new Nomenclature(
                                                    reader.IsDBNull(0) ? "" : reader.GetString(0),
                                                    reader.IsDBNull(1) ? "" : reader.GetString(1),
                                                    reader.IsDBNull(2) ? 0 : reader.GetFloat(2),
                                                    reader.IsDBNull(3) ? "" : reader.GetString(3),
                                                    reader.IsDBNull(4) ? "" : reader.GetString(4),
                                                    reader.IsDBNull(5) ? "" : reader.GetString(5),
                                                    reader.IsDBNull(6) ? "" : reader.GetString(6),
                                                    reader.IsDBNull(7) ? "" : reader.GetString(7)));
                    }
                }
            }
            finally
            {
                con.Close();
            }
ошибка вылетает тут:
C#
1
2
3
4
5
6
7
8
reader.IsDBNull(0) ? "" : reader.GetString(0),
                                                    reader.IsDBNull(1) ? "" : reader.GetString(1),
                                                    reader.IsDBNull(2) ? 0 : reader.GetFloat(2),
                                                    reader.IsDBNull(3) ? "" : reader.GetString(3),
                                                    reader.IsDBNull(4) ? "" : reader.GetString(4),
                                                    reader.IsDBNull(5) ? "" : reader.GetString(5),
                                                    reader.IsDBNull(6) ? "" : reader.GetString(6),
                                                    reader.IsDBNull(7) ? "" : reader.GetString(7)))
говорит "Заданное приведение недопустимо" (
при компиляции проблем не возникает, ошибка вылетает при заполнении "листа".
в чем может быть проблема???
если быть точнее ошибка помоему вылетает тут.

Добавлено через 59 секунд
C#
1
nm.Price = reader.IsDBNull(2) ? 0 : reader.GetFloat(2);
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
10.07.2012, 17:06
reader.IsDBNull(1) ? "" : reader.GetString(1),
reader.IsDBNull(2) ? 0 : reader.GetFloat(2)
Не понял, как вы везде строки передаете, а тут цифру.
У вас должен быть список однотипных элементов, а у вас получаются и строки и цифры. Попробуйте вместо ноля передавать пустую строку.
0
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163
10.07.2012, 17:13  [ТС]
потому что тип данных в базе float
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
10.07.2012, 17:15
Ilnur888, а вы попробуйте. Если ошибка исчезнет, значит проблема в этом, если нет - надо думать. А уж как вы решать будете: изменять БД или обрабатывать как-то по-хитрому, сами решите. Сначала локализация проблемы, потом устранение. В данном случае нужно, чтобы правильно работал метод, а что он отдаст не те данные, которые может принять БД, не важно
0
2 / 2 / 0
Регистрация: 18.01.2012
Сообщений: 163
10.07.2012, 17:22  [ТС]
я считываю данные из базы полный код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
 
namespace HTTPServer
{
    class Cache
    {
        // собственно массив с которым мы будем апперировать
        private static List<Nomenclature> lst;
        // подключение к серваку
        private SqlConnection con;
        // комадда которая берет данные с сервера
        private SqlCommand cmd;
 
        // свойство возвращает количество элементов кэша
        public static int Count
        {
            get { return lst.Count; }
        }
 
        // конструктор кэша 
        public Cache(string login, string password)
        {
            try
            {
                con = new SqlConnection(@"Data Source=cpc04;Initial Catalog=UTdata;Persist Security Info=True;User ID=" + login + ";Password=" + password);
                cmd = con.CreateCommand();
 
                cmd.CommandText = @"SELECT
                                    P.Title,
                                    P.Article,
                                    P.Price,
                                    P.OEM,
                                    P.[Cross],
                                    P.Applicance,
                                    P.Producer,
                                    P.MarkAuto
                                FROM Products P";
                // создаем новый лист
                lst = new List<Nomenclature>();
 
                // открываем созданное нами подключение
                con.Open();
 
                // заполняем наш массив данными
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    Nomenclature nm = new Nomenclature();
                    while (reader.Read())
                    {
 
                        //Nomenclature nm = new Nomenclature();
                        nm.Title = reader.IsDBNull(0) ? "" : reader.GetString(0);
                        nm.Article = reader.IsDBNull(1) ? "" : reader.GetString(1);
                        nm.Price = reader.IsDBNull(2) ? 0 : reader.GetFloat(2);
                        nm.OEM = reader.IsDBNull(3) ? "" : reader.GetString(3);
                        nm.Cross = reader.IsDBNull(4) ? "" : reader.GetString(4);
                        nm.Applicance = reader.IsDBNull(5) ? "" : reader.GetString(5);
                        nm.Producer = reader.IsDBNull(6) ? "" : reader.GetString(6);
                        nm.MarkAuto = reader.IsDBNull(7) ? "" : reader.GetString(7);
 
                        lst.Add(nm);
                    }
                }
            }
            finally
            {
                con.Close();
            }
 
        }
 
 
    }
}
и класс номенклатуры:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;
using System.Collections.Generic;
using System.Text;
 
namespace HTTPServer
{
    class Nomenclature
    {
        // наименование номенклатуры (товара)
        private string _title;
        // артикул (каталожный номер) номенклатуры (товара)
        private string _article;
        // цена в рублях
        private float _price;
        // некий номер присвоенный производителем (изготовителем)
        private string _oem;
        // некий идентификатор данного вида номенклатуры
        private string _cross;
        // определяет марку машины (например если _producer == "ВАЗ" то _appliance == "2110")
        private string _applicance;
        // изготовитель данной номенклатуры
        private string _producer;
        // марка автомобиля
        private string _MarkAuto;
 
        public string Title { get { return _title; } set { _title = value; } }
        public string Article { get { return _article; } set { _article = value; } }
        public float Price { get { return _price; } set { _price = value; } }
        public string OEM { get { return _oem; } set { _oem = value; } }
        public string Cross { get { return _cross; } set { _cross = value; } }
        public string Applicance { get { return _applicance; } set { _applicance = value; } }
        public string Producer { get { return _producer; } set { _producer = value; } }
        public string MarkAuto { get { return _MarkAuto; } set { _MarkAuto = value; } }
 
 
        // конструктор нашей номенклатуры (перегруженный можно просто создать экземпляр, а можно сразу передать в него параметры)
        public Nomenclature()
        { }
 
        public Nomenclature(string title, string article, float price, string oem, string cross, string applicance, string producer, string mark_auto)
        {
            this._title = title;
            this._article = article;
            this._price = price;
            this._oem = oem;
            this._cross = cross;
            this._applicance = applicance;
            this._producer = producer;
            this._MarkAuto = mark_auto;
        }
 
 
    }
}
Добавлено через 1 минуту
ошибка точно вылетает в этой строчке
C#
1
nm.Price = reader.IsDBNull(2) ? 0 : reader.GetFloat(2);
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
10.07.2012, 18:00
Попробуйте во всей программе сделать цену тоже строковым параметром, то есть
C#
1
2
3
4
5
6
7
8
public string Title { get { return _title; } set { _title = value; } }
        public string Article { get { return _article; } set { _article = value; } }
        public string Price { get { return _price; } set { _price = value; } }
        public string OEM { get { return _oem; } set { _oem = value; } }
        public string Cross { get { return _cross; } set { _cross = value; } }
        public string Applicance { get { return _applicance; } set { _applicance = value; } }
        public string Producer { get { return _producer; } set { _producer = value; } }
        public string MarkAuto { get { return _MarkAuto; } set { _MarkAuto = value; } }
Если поможет, то это самый простой вариант, который приходит на ум. Не знаю, чего ему не нравится

Добавлено через 7 минут
Но что про меня сказать: я ваш код скопировал, у меня компилируется без проблем (правда я эти методы не вызываю, но ошибок компиляции нету). Только один warning:
Предупреждение 1 CA1001 : Microsoft.Design : Реализуйте IDisposable для 'Program.Cache', поскольку он создает члены следующих типов IDisposable: 'SqlConnection'. c:\users\alex\documents\visual studio 2010\Projects\ConsoleApplication9\Consol eApplication9\Program.cs 98 ConsoleApplication9
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.07.2012, 18:00
Помогаю со студенческими работами здесь

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

Ошибка доступа к файлу
Ребят, с данной проблемой уже борюсь долго. Почему-то когда в директорию проекта файл записываю, то все нормально. А вот куда-либо в...

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

Ошибка доступа к файлу
Здравствуйте! Есть асинхронный сервер по сбору данных. Необходимо все получаемые данные писать в файл. Если файл создан, то никаких...

Контроль доступа к файлу Excel
Подскажите пожалуйста, есть файл Excel (2003,2007,2010), он лежит в общем доступе, его могут открывать 10 человек (по очереди, для внесения...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru