none
Необработанное исключение типа "System.ArgumentException" в mscorlib.dll VS2012 RRS feed

  • Вопрос

  • Дополнительные сведения: Не является допустимой датой OleAut.
    Всем доброго времени суток, вот такую ошибку я получаю при сборки проекта в 12 студии, в 15 таких проблем не было, если в классе убрать public DateTime t_n { get; set; }
    public DateTime t_k { get; set; }
    , тогда ошибки исключения не возникает, с чем это может быть связанно ? как можно решить данную проблему на данной студии, всем большое спасибо за ваши ответы.
    Ниже  проект с данной проблемой:

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace TestF
    {
        public class test
        {
            public float resm { get; set; }
            public float[] resp { get; set; }
            public float[] result { get; set; }
            public str_pereval pereval { get; set; }
        };
    
    
    
        [StructLayout(LayoutKind.Sequential)]
        public class str_pereval                      //Класс данных валков
        {
            public int nk { get; set; } //Номер клети
            public int N_lower { get; set; } //Номер нижнего валка
            public int N_top { get; set; } //Номер верхнего валка
            public float d_lower { get; set; } //Диаметр нижнего валка 
            public float d_top { get; set; } //Диаметр верхнего валка
            public DateTime t_n { get; set; } //Дата\Время перевалки
            public DateTime t_k { get; set; }
            public float L { get; set; } //Длина
            public float P { get; set; } //Вес в тоннах
            public float Pm { get; set; } //Вес в тоннах при прокате меньше 0.7мм
            public float Pp { get; set; } //Вес в тоннах при прокате больше либо равно 0.7 мм
            public float kal_n { get; set; }
            public float kal_v { get; set; }
            public float res_v { get; set; } //Ресурс валков
    
    
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            private float[] frez;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            private int[] irez;
    
            public float[] Frez { get { return frez; } }
            public int[] Irez { get { return irez; } }
            //  public test tester { get; set; }
        };
        public partial class MainWindow : Window
        {
            public ObservableCollection<test> List { get; private set; } 
            public ObservableCollection<str_pereval> List1 { get; private set; } 
            public MainWindow()
            {
                List  = new ObservableCollection<test>();
                List1 = new ObservableCollection<str_pereval>();
                InitializeComponent();
                DataContext = List;
            }
    
            private void button_Click(object sender, RoutedEventArgs e)
            {
                List.Clear();
                List1.Clear();
                int counter = 0;
                float[] res_val_m = new float[] { 2700, 2100, 1300, 1000, 30000, 30000, 30000, 20000 };
                float[] res_val_p = new float[] { 3500, 3000, 2200, 2000, 40000, 40000, 40000, 30000 };
                float[] objj = new float[8];
                float[] res_mm = new float[8];
                float[] res_pp = new float[8];
                using (var reader = new BinaryReader(File.OpenRead("fpereval.dat")))
                {
    
    
                    while (reader.BaseStream.Position != reader.BaseStream.Length)
                    {
    
                        var obj = ReadStruct<str_pereval>(reader);
                        var un = new test { pereval = obj, resm = res_mm[counter], resp = res_pp }; //, resm = res_mm[counter], resp = res_pp
                        if (counter < 4)
                            List.Add(un);
                        else
                            List1.Add(obj);
                        counter++;
                    }
                }
           /**/
            int j = 0;
                for (int i = 0; i< 4; i++)
                {
                    
                    objj[i] = 1 - (List[i].pereval.Pm / res_val_m[i]) - (List[i].pereval.Pp / res_val_p[i]);
                    if (objj[i] > 0)
                    {
                        res_mm[i] = res_val_m[i] * objj[i];
                        res_pp[i] = res_val_p[i] * objj[i];
                       
                    }
                    else
                    { res_mm[i] = 0; res_pp[i] = 0; }
    
    
    List.Add(new test { resm = res_mm[i], resp = res_pp, result = objj });
                }
             
                /**/
    
            }
    
            T ReadStruct<T>(BinaryReader reader) where T : class, new()
            {
                byte[] rawData = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
                GCHandle handle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
                var returnObject = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
                handle.Free();
                return returnObject;
            }
        }
    }
    

    исключение в этой строке :

    var returnObject = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));

    Всем спасибо

    11 декабря 2015 г. 8:43

Ответы

  • В общем то подобная проблема ожидаема при любой смене версий так как ваш код имеет ряд проблем.

    0. Такое использование структур опасно и нестабильно в целом. Для надежности замените весь этот код сохранением данных в XML или JSON формате. Это гарантирует переносимость и совместимость версий. 

    1. Нет никаких гарантий как именно будут расположены поля созданные компилятором для автоматических свойств. Уберите все автоматические свойства и замените их полями (можно private). Если надо добавьте свойства которые будут возвращать/устанавливать эти поля.

    2. Замените DateTime на конкретный формат используемый в источнике (например double) . Используйте свойство для преобразование в DateTime. Не используйте поля никаких типов кроме простейших (double, float, int и т.п.).

    3. Подумайте об использовании LayoutKind.Explicit и атрибутов FieldOffset.

    4. Добавьте тесты которые будут проверять правильность положения полей.

    Советы по работу с форумом:

    1. Терпение, терпение и еще раз терпение. Никаких "апов" в течении по меньшей мере недели.

    2. Одна тема - один вопрос.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа Ethernets 16 декабря 2015 г. 18:50
    15 декабря 2015 г. 20:08
    Модератор

Все ответы

  • Все еще актуально
    14 декабря 2015 г. 16:14
  • На 13-й студии такая же проблема, с чем это может быть связанно не понимаю,

    Проблема наблюдается не только у меня. Коллеги давайте разберемся вместе с данной проблемой, я так полагаю что не правильно формируется структура str_pereval и DataTime смещается из за чего и происходит данное исключение, и еще в сравнении с 15 студией заметил что если объявлять коллекцию таким способом:
    C#Выделить код
    1
    
     public ObservableCollection<test> List { get; private set; }  = new ObservableCollection<test>();
    Тогда все нормально, и чтение и сборка пакета. Но так как предыдущие версии студии ругаются и приходиться объявлять коллекцию следующем путем :
    C#Выделить код
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
      public partial class MainWindow : Window
        {
            public ObservableCollection<test> List { get; private set; } 
    public MainWindow()
            {
                List  = new ObservableCollection<test>();
                InitializeComponent();
                DataContext = List;
            }
    ...}
    сразу получаем исключение. Может есть у кого какие интересные мыли и варианты по этому поводу ? 
    Всем спасибо

    15 декабря 2015 г. 18:15
  • В общем то подобная проблема ожидаема при любой смене версий так как ваш код имеет ряд проблем.

    0. Такое использование структур опасно и нестабильно в целом. Для надежности замените весь этот код сохранением данных в XML или JSON формате. Это гарантирует переносимость и совместимость версий. 

    1. Нет никаких гарантий как именно будут расположены поля созданные компилятором для автоматических свойств. Уберите все автоматические свойства и замените их полями (можно private). Если надо добавьте свойства которые будут возвращать/устанавливать эти поля.

    2. Замените DateTime на конкретный формат используемый в источнике (например double) . Используйте свойство для преобразование в DateTime. Не используйте поля никаких типов кроме простейших (double, float, int и т.п.).

    3. Подумайте об использовании LayoutKind.Explicit и атрибутов FieldOffset.

    4. Добавьте тесты которые будут проверять правильность положения полей.

    Советы по работу с форумом:

    1. Терпение, терпение и еще раз терпение. Никаких "апов" в течении по меньшей мере недели.

    2. Одна тема - один вопрос.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа Ethernets 16 декабря 2015 г. 18:50
    15 декабря 2015 г. 20:08
    Модератор
  • В общем то подобная проблема ожидаема при любой смене версий так как ваш код имеет ряд проблем.

    0. Такое использование структур опасно и нестабильно в целом. Для надежности замените весь этот код сохранением данных в XML или JSON формате. Это гарантирует переносимость и совместимость версий. 

    1. Нет никаких гарантий как именно будут расположены поля созданные компилятором для автоматических свойств. Уберите все автоматические свойства и замените их полями (можно private). Если надо добавьте свойства которые будут возвращать/устанавливать эти поля.

    2. Замените DateTime на конкретный формат используемый в источнике (например double) . Используйте свойство для преобразование в DateTime. Не используйте поля никаких типов кроме простейших (double, float, int и т.п.).

    3. Подумайте об использовании LayoutKind.Explicit и атрибутов FieldOffset.

    4. Добавьте тесты которые будут проверять правильность положения полей.

    Советы по работу с форумом:

    1. Терпение, терпение и еще раз терпение. Никаких "апов" в течении по меньшей мере недели.

    2. Одна тема - один вопрос.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Доброго вам времени суток, большое спасибо за ваши советы, и ваш ответ.

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

    0- Я не могу изменить формат, по тому как бинарный файл формируется из другого приложения. Которое написано в далеких 2000-х на Builder'e . И модернизация данного проекта если и будет, то уже скорее всего с использованием БД.

    1- Приведу пример, правильно я понял ваше предложение ? 

    class Person
    {
        private string name;
     
        public string Name
        {
            get
            {
                return name;
            }
     
            set
            {
                name = value;
            }
        }
    }

    2. Замените DateTime на конкретный формат используемый в источнике (например double) . - 

    Я уже пробовал заменить на double. Тогда вся моя структура заполняется каким-то не понятным мусором, который заполняется из бинарного файла.

    3 - 4: Для меня вообще пока новые слова, и т.д (сейчас буду искать и читать теорию)

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

    Еще раз большое вам спасибо.

    P.s По форуму я учту ваши советы, спасибо.





    • Изменено Ethernets 16 декабря 2015 г. 6:07
    16 декабря 2015 г. 5:27
  • 0. Сочувствую.

    1. Да, правильно. Очередность полей, их тип/размеры и выравнивание должны быть точно такие же как в "другом приложении написанном на билдере в 2000", иначе структура будет заполняться непонятным мусором. С учетом разницы в разрядности и неизвестно каком выравнивании "билдера в 2000" это возможно потребует указания положения всех полей из п.3.

    2. Это потому что имеется разница описанное в 1.

    3,4. Век живи, век учись.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    16 декабря 2015 г. 6:49
    Модератор
  • 0. Сочувствую.

    1. Да, правильно. Очередность полей, их тип/размеры и выравнивание должны быть точно такие же как в "другом приложении написанном на билдере в 2000", иначе структура будет заполняться непонятным мусором. С учетом разницы в разрядности и неизвестно каком выравнивании "билдера в 2000" это возможно потребует указания положения всех полей из п.3.

    2. Это потому что имеется разница описанное в 1.

    3,4. Век живи, век учись.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    0. Спасибо.

    1- Буду сейчас пробовать. Единственное что я не имею представления как уйти от этого участка 

     public ObservableCollection<test> List { get; private set; }  = new ObservableCollection<test>();

    Аналогично как и со структурой ? тогда как объявить коллекцию,  помогите пожалуйста как это сделали бы вы, если можно пример.

    Также не понятен следующий вопрос, если у меня структура вызывается из структуры, тогда как уйти от автоматических свойств ? 

      public class test
        {
            public float resm { get; set; }
            public float[] resp { get; set; }
            public float[] result { get; set; }
            public str_pereval pereval { get; set; }
        };
    
    
    
        [StructLayout(LayoutKind.Sequential)]
        public class str_pereval                      //Класс данных валков
        {
            public int nk { get; set; } //Номер клети
            public int N_lower { get; set; } //Номер нижнего валка
            public int N_top { get; set; } //Номер верхнего валка
            public float d_lower { get; set; } //Диаметр нижнего валка 
            public float d_top { get; set; } //Диаметр верхнего валка
            public DateTime t_n { get; set; } //Дата\Время перевалки
            public DateTime t_k { get; set; }
            public float L { get; set; } //Длина
            public float P { get; set; } //Вес в тоннах
            public float Pm { get; set; } //Вес в тоннах при прокате меньше 0.7мм
            public float Pp { get; set; } //Вес в тоннах при прокате больше либо равно 0.7 мм
            public float kal_n { get; set; }
            public float kal_v { get; set; }
            public float res_v { get; set; } //Ресурс валков
    
    
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            private float[] frez;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            private int[] irez;
    
            public float[] Frez { get { return frez; } }
            public int[] Irez { get { return irez; } }
            //  public test tester { get; set; }
        };

    и как объявить данный участок кода :

     public str_pereval pereval { get; set; }

    Также не понятна эта часть :

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] private float[] frez; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] private int[] irez; public float[] Frez { get { return frez; } } public int[] Irez { get { return irez; } }

    Сколько памяти будет выделено для каждого поля, объявлять поверх маршалинга ?

    Спасибо

    2- Нет у вас случайно алгоритма преобразования из типа double в понятную для нас Дату\Время (или я думаю не в том направлении ?)

    3- Почитал, разобрался, буду практиковать. (интересная тема фиксированного выделения памяти для каждого поля). Спасибо

    4- На этот совет, ответов не нашел. Очень хотелось бы так же разобраться. Если можно приведите пример. Спасибо


    • Изменено Ethernets 16 декабря 2015 г. 7:27
    16 декабря 2015 г. 7:17
  • Все структуры которые используются таким образом подлежат изменению, все автоматические свойства в них - удалению. Так же вместо class в общем случае следует использовать struct. 

    Ссылки и указатели конечно же не допускаются. Если они у вас есть то ничего работать не будет. Все другие структуры, строки и массивы - только по значению в теле структуры, все фиксированного размера. Указанная ниже часть как раз это и делает - массив размером 16 байтов находится в самой структуре, ссылки на него нет:

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    private float[] frez;

    Если есть поля переменных размеров (что бывает в родном коде) то возникают дополнительные сложности. Будем наедятся у вас их нет.

    Памяти будет выделено по размеру поля. Это определяется размером типа данных (например float - 4 байта) и, в случае массивов, числом элементов в массиве. Вам надо знать все эти размеры как в родном коде, так и в управляемом. Иногда они не совпадают.

    В общем, я рекомендую такую методику:

    1. Распишите всю структуру которую надо загрузить с указанием всех полей, их типов, размеров и положения.

    2. Создайте эквивалент в управляемом коде.

    3. Пробуйте пока не заработает.

    Что до перевода double в дату/время то оставьте это на потом когда все данные будут успешно загружены. Это задача проста, надо лишь знать как именно закодирована дата/время в double. Типично это число каких то временных интервалов (например секунд или миллисекунд или каких то еще) с какого то момента времени (например с 00:00 1/1/1970 или 00:00 1/1/0001). Вы должны знать что именно представляет из себя дата в данном конкретном случае, после этого преобразовать ее не сложно.



    This posting is provided "AS IS" with no warranties, and confers no rights.

    16 декабря 2015 г. 17:15
    Модератор
  • Все структуры которые используются таким образом подлежат изменению, все автоматические свойства в них - удалению. Так же вместо class в общем случае следует использовать struct. 

    Ссылки и указатели конечно же не допускаются. Если они у вас есть то ничего работать не будет. Все другие структуры, строки и массивы - только по значению в теле структуры, все фиксированного размера. Указанная ниже часть как раз это и делает - массив размером 16 байтов находится в самой структуре, ссылки на него нет:

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    private float[] frez;

    Если есть поля переменных размеров (что бывает в родном коде) то возникают дополнительные сложности. Будем наедятся у вас их нет.

    Памяти будет выделено по размеру поля. Это определяется размером типа данных (например float - 4 байта) и, в случае массивов, числом элементов в массиве. Вам надо знать все эти размеры как в родном коде, так и в управляемом. Иногда они не совпадают.

    В общем, я рекомендую такую методику:

    1. Распишите всю структуру которую надо загрузить с указанием всех полей, их типов, размеров и положения.

    2. Создайте эквивалент в управляемом коде.

    3. Пробуйте пока не заработает.

    Что до перевода double в дату/время то оставьте это на потом когда все данные будут успешно загружены. Это задача проста, надо лишь знать как именно закодирована дата/время в double. Типично это число каких то временных интервалов (например секунд или миллисекунд или каких то еще) с какого то момента времени (например с 00:00 1/1/1970 или 00:00 1/1/0001). Вы должны знать что именно представляет из себя дата в данном конкретном случае, после этого преобразовать ее не сложно.



    This posting is provided "AS IS" with no warranties, and confers no rights.

    Сделал следующим образом: 

      public class test
        {
           private float resm;
           public float Resm
           {
               get { return resm; }
               set { resm = value; }
           }
    
            private float[] resp ; //{ get; set; }
            public float[] Resp
            {
                get { return resp; }
                set { resp = value; }
            }
           public float[] result { get; set; }
           private str_pereval Pereval;  
           public str_pereval pereval
           {
               get { return Pereval; }
               set { Pereval = value; }
           }
               //{ get; set; }
        };
    
    
    
       [StructLayout(LayoutKind.Explicit, Size = 104)]  // [StructLayout(LayoutKind.Sequential)]
        public class str_pereval                      
        {
           [FieldOffset(0)]  private int nk;
           [FieldOffset(4)]  private int n_lower;
           [FieldOffset(8)]  private int n_top;
           [FieldOffset(12)] private float d_lower;
           [FieldOffset(16)] private float d_top;
           [FieldOffset(20)] private double t_n;
          // [FieldOffset(28)] public double t_k;
           [FieldOffset(40)] private float l;
           [FieldOffset(44)] private float p;
           [FieldOffset(48)] private float pm;
           [FieldOffset(52)] private float pp;
           [FieldOffset(56)] public float kal_n;
           [FieldOffset(60)] public float kal_v;
           [FieldOffset(64)] private float res_v;
           public int Nk
           {
               get { return nk; }
               set { nk = value; }
           }
           public int N_lower
           {
               get { return n_lower; }
               set { n_lower = value; }
           }
           public int N_top
           {
               get { return n_top; }
               set { n_top = value; }
           }
           public float D_lower
           {
               get { return d_lower; }
               set {d_lower = value;}
           }
           public float D_top
           {
               get { return d_top; }
               set { d_top = value; }
           }
    
           public float P
           {
               get { return Convert.ToSingle(Math.Round(p)); }
               set {p = value;}
           } 
    
           public float L
           {
               get { return Convert.ToSingle(Math.Round(l/1000.0)); }
               set {l = value;}
           }
           
           public float Pm
           {
               get { return Convert.ToSingle(Math.Round(pm)); }
               set { pm = value; }
           }
    
           public float Pp
           {
               get { return Convert.ToSingle(Math.Round(pp)); }
               set { pp = value; }
           }
           public float Res_v
           {
               get { return Convert.ToSingle(Math.Round(res_v*100)); }
               set { res_v = value; }
           }
    
           public double T_n
           {
               get { return t_n; }
               set { t_n = value; }
           }

    Теперь осталось преобразовать дату и время. 

    И с коллекцией не разобрался что же все-таки с ней делать, что бы уйти от автоматических свойств. Хотя вроде и так работает 

    2. "Создайте эквивалент в управляемом коде." - не понял о чем именно вы говорите.

    Если я что-то не правильно сделал, жду вашего мнения и т.д. Большое вам спасибо 

    P.s. Жду вас в следующей теме.

    16 декабря 2015 г. 18:49