SafeArrayTypeMismatchException: указанный массив не имеет ожидаемого типа.

Я пытаюсь прочитать данные с сервера OPC DA. Я использую метод SyncRead SyncRead(short Source, int NumItems, ref Array ServerHandles, out Array Values, out Array Errors, out object Qualities, out object TimeStamps); Проблема в том, что я точно не знаю тип массива значений параметров. я делаю это как

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OPCAutomation;
using EasyModbus;
using System.Threading;
using System.IO;


Array ServerHandles = new Array[ObjOPCGroup.OPCItems.Count];
Array Values = new Array[ObjOPCGroup.OPCItems.Count];
Array Errors = new Array[ObjOPCGroup.OPCItems.Count];
object Qualities = new object();
object TimeStamps = new object();
Array Values = new Array[ObjOPCGroup.OPCItems.Count];

ObjOPCGroup.SyncRead(
   (short)OPCDataSource.OPCDevice,
   ObjOPCGroup.OPCItems.Count,
   ref ServerHandles,
   out Values,
   out Errors,
   out Qualities,
   out TimeStamps
   );

когда я запускаю приложение, я получаю сообщение об ошибке: System.Runtime.InteropServices.SafeArrayTypeMismatchException: указанный массив не имеет ожидаемого типа

Кто-нибудь может мне помочь?

Спасибо


person Witold Lisiecki    schedule 27.02.2020    source источник
comment
небольшое примечание: вы объявляете Values дважды; это опечатка?   -  person Marc Gravell    schedule 27.02.2020
comment
Должен быть массивом int[].   -  person Hans Passant    schedule 28.02.2020


Ответы (1)


new Array[length] — это массив массивов; вам, вероятно, нужен массив чего-то более подходящего, например, new int[length] для массива целых чисел или new string[length] для массива строк. Мы не знаем, что такое API, поэтому не можем сказать, какими они должны быть. Но они почти наверняка не должны быть массивами Array.

Кроме того: большинство из них передаются как out параметры, так что вам вероятно даже не нужно ничего инициализировать, кроме ServerHandles. Все остальное, вероятно, может быть null? или просто инициализирован через out var т.е.

Array serverHandles = new SomeOtherTypeHere[ObjOPCGroup.OPCItems.Count];

ObjOPCGroup.SyncRead(
   (short)OPCDataSource.OPCDevice,
   ObjOPCGroup.OPCItems.Count,
   ref serverHandles,
   out var values,
   out var errors,
   out var qualities,
   out var timeStamps
   );
person Marc Gravell    schedule 27.02.2020
comment
Я изменил его, как Вы написали, и объявил Array serverHandles = new long[ObjOPCGroup.OPCItems.Count]; , потому что я нашел этот тип данных в некоторых документах OPC DA Automation. Сообщение об ошибке все еще отображается. Как я могу проверить, какая переменная или параметр неверны? - person Witold Lisiecki; 28.02.2020
comment
Хорошо, я изменил объявление на int[] Array ServerHandles = new int[ObjOPCGroup.OPCItems.Count]; и получил сообщение: Попытка чтения или записи защищенной памяти. Часто это указывает на то, что другая память повреждена. - person Witold Lisiecki; 28.02.2020
comment
После изменений у меня есть сообщение: System. ArgumentException: Value does not fall within the expected range - person Witold Lisiecki; 28.02.2020
comment
Без знания API, о котором идет речь, я не могу ответить, извините. Откровенно говоря, слои P/Invoke сложны, и обычно их лучше всего обернуть кем-то, кто находится рядом с вызываемой вещью. - person Marc Gravell; 28.02.2020
comment
Эй Марк, спасибо за Вашу помощь. Я нашел решение этой последней проблемы. Я заполнил объект ObjOPCGroup.OPCItems.AddItem("Some.Variable", 1) без сохранения ServerHanle в массиве Array ServerHandles = new int[ObjOPCGroup.OPCItems.Count];. Когда этот массив без хэндлов, то эта ошибка System. ArgumentException: отображается значение, выходящее за пределы ожидаемого диапазона. В качестве неплохой справки могу прикрепить ссылку, как ее использовать: stackoverflow.com/questions/30866803/ . Теперь я могу отметить проблему как решенную - person Witold Lisiecki; 28.02.2020