Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.11.2014, 11:51   #1
KonstantinLitvn
Новичок
Джуниор
 
Регистрация: 13.11.2014
Сообщений: 4
По умолчанию CallbackOnCollectedDelegate was detected

Помогите решить проблему

Есть PCI плата и библиотека для упраления PCI-Dask.dll

Есть пневмосистема, которая состоит из 24 пневмопушек. На каждой пневмопушке установлен датчик срабатывания.
Есть форма с 24 кнопками и 24 textboxами. При нажатии одной из 24 кнопок срабатывает соответствующая пневмопушка. А в один из 24 textbox'ов выводится количество выстрелов от соответствующей пневмопушки. Но возникает следующая ошибка.

CallbackOnCollectedDelegate was detected
Message: A callback was made on a garbage collected delegate of type 'Pci7442!Pci7442.Card+Multidelegate ::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

Причем, возникает не сразу, а после примерно 40 нажатий на различные кнопки.
Так же было замечено, что при стрельбе с отсутствием воздуха (датчики не срабатывают в этом случае), проблема не возникает.
Возможно проблема методе GetDataFromDigitalInput()
Код:
public class Pci7442
    {
    [DllImport("PCI-Dask.dll")]
	public static extern short DI_ReadLine (ushort cardNumber, ushort port, ushort line, out ushort state);
[DllImport("PCI-Dask.dll")]
    public static extern short DIO_GetCOSLatchDataInt32(ushort wCardNumber, byte port, out uint cosLData);
	[DllImport("PCI-Dask.dll")]
	public static extern short DO_WriteLine (ushort cardNumber, ushort port, ushort line, ushort value);

    }
}

public partial class ButtonControl : UserControl
    {
        public ButtonControl()
        {
            InitializeComponent();
        }
       
        private const ushort CardPci7442 = 0;
        private readonly Dictionary<string, ushort> _tableOfLine = new Dictionary<string, ushort>();
        private ushort _numberOfPort;
        public void SetNumberOfPort(ushort numberOfPort)
        {
            _numberOfPort = numberOfPort;
        }
        
        private void btn_Click(object sender, EventArgs e)
        {
                var linesControl = new LineControl();
                var cklickedButton = (Button)sender;
                var line = _tableOfLine[cklickedButton.Tag.ToString()];
                
               // linesControl.ShotLineOutput(CardPci7442, line, _numberOfPort);
                Task.Run(() => linesControl.ShotLineOutput(CardPci7442, line, _numberOfPort)); 
          
         }
    }
	class LineControl:ILineControl
    {
        public void ShotLineOutput(ushort numberOfCard, ushort numberOfLine, ushort port)
        {
            for (var i = 0; i < 5; i++)
            {
               Pci7442.DO_WriteLine(numberOfCard, port, numberOfLine, Pci7442.Low);
                    Thread.Sleep(70);
                    Pci7442.DO_WriteLine(numberOfCard, port, numberOfLine, Pci7442.High);
                    Thread.Sleep(70);
          }
        }
    }
class Card : ICard
    {
        public delegate void Multidelegate();
        private const ushort CardPci7442 = 0;
      
	  public void InitCosInterrupt()
        {
            long hEvent;
            Multidelegate callbackAddr = GetDataFromDigitalInput;
        }
        
        private uint _cosLData;
        private void SetCosLData(uint value)
        {
            _cosLData = value;
        }
        public uint GetCosLData()
        {
            return _cosLData;
        }
        private void GetDataFromDigitalInput()
        {
            uint cosLData;
            Pci7442.DIO_GetCOSLatchDataInt32(CardPci7442, 0, out cosLData);
            SetCosLData(cosLData);
            GC.KeepAlive(this);
        }
    }
 public partial class Pci7442Form : Form
    {
        private readonly ICard _card = new Card();
        private const ushort CardPci7442 = 0;
        public Pci7442Form()
        {
            InitializeComponent();
            _card.RegisterCard(CardPci7442);
            Thread.Sleep(100);
            _card.InitCosInterrupt();


            btnControl1.CreateButtons();
            btnControl1.SetNumberOfPort(0);
         
        }
   

        private void GetCountOfShoots_Tick(object sender, EventArgs e)
        {
                var aRandom = new Random();
                var numberOfSensor = Math.Log(_card.GetCosLData(), 2);
                if (!double.IsNegativeInfinity(numberOfSensor))
                {
                    var t = txBxUserControl1.TextBoxsArray[Convert.ToInt32(numberOfSensor)];
                     //var t = txBxUserControl1[aRandom.Next(0, 24)];
                    t.Value++;
                }
         }

     }
}

Последний раз редактировалось Stilet; 13.11.2014 в 12:39.
KonstantinLitvn вне форума Ответить с цитированием
Старый 13.11.2014, 16:55   #2
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

По-моему тут вы что-то странное делаете.
Код:
        public delegate void Multidelegate();
      
	public void InitCosInterrupt()
        {
            long hEvent;
            Multidelegate callbackAddr = GetDataFromDigitalInput;
        }
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 14.11.2014, 12:27   #3
KonstantinLitvn
Новичок
Джуниор
 
Регистрация: 13.11.2014
Сообщений: 4
По умолчанию

Alex11223, моя ошибка, опрометчиво выкинул часть метода при форматировании, вот полный вариант. То есть при возникновении прерывания выполняется метод GetDataFromDigitalInpu(); который считывает состояния датчиков Pci7442.DIO_GetCOSLatchDataInt32(Ca rdPci7442, 0, out cosLData);

Код:
 public delegate void Multidelegate();
      
	public void InitCosInterrupt()
        {
            long hEvent;
            Multidelegate callbackAddr = GetDataFromDigitalInput;
            Pci7442.DIO_SetCOSInterrupt32(CardPci7442,0,0xffffffff, out hEvent, false);
            Pci7442.DIO_INT1_EventMessage(CardPci7442, Pci7442.Int1Cos0,0,0, callbackAddr);
        }


public class Pci7442
    {
    
       [DllImport("PCI-Dask.dll")]
       public static extern short DIO_SetCOSInterrupt32(ushort wCardNumber, byte port, uint ctl, out long hEvent, bool bManualReset);
       [DllImport("PCI-Dask.dll")]
       public static extern short DIO_INT1_EventMessage(ushort cardNumber, short int1Mode, uint windowHandle, uint message, MulticastDelegate callbackAddr);

    }

Последний раз редактировалось KonstantinLitvn; 14.11.2014 в 12:30.
KonstantinLitvn вне форума Ответить с цитированием
Старый 14.11.2014, 12:43   #4
KonstantinLitvn
Новичок
Джуниор
 
Регистрация: 13.11.2014
Сообщений: 4
По умолчанию

Я так понимаю, что при обратном вызове из неуправляемого кода сборщик мусора уничтожает ссылку callbackAddr на метод GetDataFromDigitalInput (Multidelegate callbackAddr = GetDataFromDigitalInput;)
KonstantinLitvn вне форума Ответить с цитированием
Старый 14.11.2014, 12:43   #5
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Код:
public void InitCosInterrupt()
{
    Multidelegate callbackAddr = ...;
}
уничтожается после завершения InitCosInterrupt.

Наверно его просто полем этого класса сделать надо было, если InitCosInterrupt вызывается только один раз (ну или точнее если не вызывается пока текущий callbackAddr еще используется).

А, точнее если там один и тот же GetDataFromDigitalInput, то наверно можно даже так:
Код:
private readonly Multidelegate _callbackAddr = GetDataFromDigitalInput;
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 14.11.2014 в 12:52.
Alex11223 вне форума Ответить с цитированием
Старый 14.11.2014, 14:36   #6
KonstantinLitvn
Новичок
Джуниор
 
Регистрация: 13.11.2014
Сообщений: 4
По умолчанию

Да, это заработало, спасибо!
Но не совсем понял почему.
KonstantinLitvn вне форума Ответить с цитированием
Старый 14.11.2014, 14:39   #7
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Чего непонятного? При завершении InitCosInterrupt нигде больше не остается ссылок на объект (если callbackAddr локальная переменная этого метода) и сборщик мусора его уничтожает.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
*** glibc detected *** double free or corruption Stilet Linux (Ubuntu, Debian, Red Hat, CentOS, Mint) 2 13.05.2014 20:50
GetDIBits пишет за буфеер => Heap corruption detected. TwiX Win Api 2 16.11.2013 22:27
RAW audio finder (16 kB detected) RibGeDx Мультимедиа в Delphi 1 03.02.2013 11:53
Ambiguous name detected: CommandButton2_Click ramzes777 Microsoft Office Excel 3 23.12.2011 19:46
detected IDE drivers nikox12 Компьютерное железо 1 02.05.2011 19:51