Деконструктор, утилизировать не знаю что использовать - PullRequest
0 голосов
/ 28 марта 2012

Я столкнулся с небольшой проблемой в моей программе.У меня есть класс с сокетом в нем и некоторые объявленные переменные.

Теперь, когда я покидаю страницу, где был определен класс,

Class someclass = new class;

Я хочу, чтобы класс был "уничтожен", чтобы я мог открыть новый сокет с тем же портом /IP на другой странице.(теперь порт и IP-адрес, кажется, заблокированы классом, который я не деконструирую / не утилизирую / gc)

Потому что у меня есть фон на c ++, и я впервые использую c #.Я понятия не имею, с чего начать, потому что в c ++ вы просто вызываете деструктор.Это очистит ваш класс и удалит все активные сокеты / переменные.Но как мне сделать это в C #.Я прочитал кое-что о классе Idisposable, но это не проясняет ситуацию.Также есть сборщик мусора и обычный деконструктор.Я не знаю, что использовать, и более важно, как его использовать.


Редактировать 1

Как сказано ниже в комментариях: этот проект является проектом Windows Phone, чтоиспользует внешнюю библиотеку для создания сокета и настройки связи между телефоном Windows и ПЛК Beckhoff.

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

public class TwincatVar<T> : IDisposable where T : IConvertible
{

    public AdsClient _AdsClient;
    private string _PlcVar;
    private uint _VarHandle;
    private T _Data;
    private DateTime _TimeStamp;
    private bool disposed = false;
    public EventHandler DataChanged;

    //constructor
    public TwincatVar(ref AdsClient AdsClient, string PlcVar)
    {
        //Hook up to the reference of AdsClient
        _AdsClient = AdsClient;

        _PlcVar = PlcVar;

    }

    public async Task InitFunction()
    {

            _VarHandle = await _AdsClient.GetSymhandleByNameAsync(_PlcVar);

            Debug.WriteLine(_VarHandle.ToString());

            _Data = await _AdsClient.ReadAsync<T>(_VarHandle);

            _AdsClient.AddNotificationAsync<T>(_VarHandle, AdsTransmissionMode.OnChange, 1000, this);

    }


    public T Data
    {

        get { return _Data; }
        set
        {
            _Data = value;
            _AdsClient.WriteAsync<T>(_VarHandle, value);
        }
    }

    public DateTime TimeStamp { get { return _TimeStamp; } }

    public void OnDataChangeEvent(T newData)
    {
        _TimeStamp = DateTime.Now;
        _Data = newData;

        //Raise the event
        if (DataChanged != null)
        {
            DataChanged(this, new EventArgs());
        }
    }

}

/ * Заметил: IDisposable, потому что я уже пытался реализовать его, но это не сработало.* /

public class TwincatDevice : IDisposable
{
    public AdsClient AdsClient;

    //Twincatdevice constructor
    public TwincatDevice(string amsNetIdSource, string ipTarget, string amsNetIdTarget, ushort amsPortTarget = 801)
    {
        AdsClient = new AdsClient(amsNetIdSource, ipTarget, amsNetIdTarget, amsPortTarget);
        AdsClient.OnNotification += DistributeEvent;
    }

    public static void DistributeEvent(object sender, AdsNotificationArgs e)
    {
        AdsNotification notification = e.Notification;


        switch (Type.GetTypeCode((notification.TypeOfValue)))
        {
            case TypeCode.Boolean: ((TwincatVar<bool>)notification.UserData).OnDataChangeEvent((bool)(notification.Value)); break;
            case TypeCode.Byte: ((TwincatVar<byte>)notification.UserData).OnDataChangeEvent((byte)(notification.Value)); break;
            case TypeCode.Int16: ((TwincatVar<short>)notification.UserData).OnDataChangeEvent((short)(notification.Value)); break;
            case TypeCode.Int32: ((TwincatVar<int>)notification.UserData).OnDataChangeEvent((int)(notification.Value)); break;
            case TypeCode.Single: ((TwincatVar<float>)notification.UserData).OnDataChangeEvent((float)(notification.Value)); break;
            case TypeCode.Double: ((TwincatVar<double>)notification.UserData).OnDataChangeEvent((double)(notification.Value)); break;
            case TypeCode.UInt16: ((TwincatVar<ushort>)notification.UserData).OnDataChangeEvent((ushort)(notification.Value)); break;
            case TypeCode.UInt32: ((TwincatVar<uint>)notification.UserData).OnDataChangeEvent((uint)(notification.Value)); break;
            case TypeCode.String: ((TwincatVar<string>)notification.UserData).OnDataChangeEvent((string)(notification.Value)); break;
        }
    }
}

В приведенном ниже коде я объявляю свои «переменные twincat», которые я подключаю к событию datachange.Кроме того, они связаны с переменной ".name" в plc.

 public class MainPageViewModel : ViewModelBase
{
    public TwincatDevice client;       
    public Device _device0;
    public Device _device1;
    public Device _device2;  
    public Devices DeviceList = new Devices();
    public TwincatVar<string> Version;

    //View Model
    public MainPageViewModel()
    {
        //Create devices with initual values
        _device0 = new Device("Device Name", "Status", "Version");
        _device1 = new Device("Device Name", "Status", "Version");
        _device2 = new Device("Device Name", "Status", "Version");

        //Add devices to observablecollection
        DeviceList.Add(_device0);
        DeviceList.Add(_device1);
        DeviceList.Add(_device2);

        // create the connection with the beckhoff device
        _Create_TwincatDevice();
        _Create_Twincatvars();
    }

    ~MainPageViewModel()
    {
    }

    public void _Create_TwincatDevice()
    {
        // This is where the socket is openend !!

//Create TwincatDevice
        client = new TwincatDevice(amsNetIdSource: "192.168.11.216.1.1",
                                   ipTarget: "192.168.11.126",
                                   amsNetIdTarget: "192.168.11.126.1.1");        

    }

    public async Task _Create_Twincatvars()
    {
        // Create Twincat Variable
        Version = new TwincatVar<string>(ref client.AdsClient, ".Version");
        // Init Twincat Variable

        await Version.InitFunction();
        Version.DataChanged += (o, e) =>
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => { _device0.Version = Version.Data; });
        };



        // TwincatVar<type> Name = new TwincatVar<type>(reference to TwincatDevice, "Variable name PLC");

    }

}

}

И, наконец, что не менее важно.В «коде страницы» (mainpage.xaml.cs) я создаю экземпляр MainViewModel и устанавливаю для него значение datacontext для привязки.

private MainPageViewModel _MV;
_MV = new MainPageViewModel();
Device_listbox.DataContext = _MV.DeviceList;

Надеюсь, это поможет вам, ребята, помочь мне:)

1 Ответ

3 голосов
/ 28 марта 2012

В отличие от C ++, .NET не допускает явного уничтожения экземпляра, выделенного сборщиком мусора (классы и типы / типы значений в штучной упаковке как члены экземпляра типа, выделенного через сборщик мусора). Это потому, что сборщик мусора позаботится о том, чтобы убирать за вами, когда сочтет это необходимым (временной интервал, нагрузка на память и т. Д.). Если вам нужно высвободить ресурсы на месте, вам нужно явно вызвать метод. Вы можете назвать этот метод как «Очистка». .NET уже поставляется с хорошо принятым шаблоном для этого. Имя метода - Утилизация. (Вы можете реализовать метод Dispose с нулевыми параметрами и пустым типом возврата или просто реализовать интерфейс IDisposable. Наименование метода как «Dispose», а не «Cleanup» дает вам лучшую поддержку инструментов и позволяет использовать оператор «using» 'в которой вы определяете область, в которой должен использоваться ваш экземпляр, и который автоматически вызывает метод Dispose в конце блока области.

Пожалуйста, см. http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.71).aspx для получения подробной информации о реализации метода Dispose и наилучшей практики использования его в сочетании с деструктором (и, по сути, сборщиком мусора)

...