解构者,处置don';I don’我不知道该用什么

本文关键字:don 我不知道 什么 处置 | 更新日期: 2023-09-27 18:29:25

我在程序中遇到了一个小问题。我有一个类,里面有一个Socket和一些声明的变量。

现在,当我离开定义类的页面时,

Class someclass = new class;

我希望类被"销毁",这样我就可以在另一个页面上打开一个具有相同端口/ip的新套接字。(现在端口和ip地址似乎被类锁定了,我不解构/dispose/g.c)

因为我有c++背景,这是我第一次使用c#。我不知道从哪里开始,因为在c++中,你只需要调用析构函数。这将清理您的类并删除所有活动的套接字/变量。但是我如何在c#中实现这一点。我读过一些关于Idisposable类的东西,但这并没有让事情变得更清楚。还有垃圾收集器和普通的解构器。我不知道该用什么,更重要的是如何使用。


编辑1

正如下面的评论所说:这个项目是一个windows phone项目,它使用一个外部库来创建一个插座,并在windows phone和Beckhoff PLC之间建立通信。

我在原始库的顶部创建了一个额外的层,使我的变量更容易声明。额外的一层看起来像这样:

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事件。此外,这些都连接到plc上的".name"变量。

 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;

我希望这能有所帮助,这样你们就能帮助我:)

解构者,处置don';I don’我不知道该用什么

与C++相比,.NET不允许显式销毁垃圾收集器分配的实例(类和装箱值类型/值类型是通过垃圾收集器分配类型的实例的成员)。这是因为当垃圾回收器认为必要时(定时间隔、内存压力等),它会在您之后进行清理。如果需要当场释放资源,则需要显式调用一个方法。您可以将此方法命名为类似"清理"的名称。NET已经提供了一个被广泛采用的模式。方法名为Dispose。(您可以实现一个具有零参数和void返回类型的Dispose方法,也可以简单地实现IDisposable接口。将该方法命名为"Dispose"而不是"Cleanup"可以为您提供更好的工具支持,并允许使用"using语句",在该语句中定义应使用实例的作用域,并在作用域末尾自动调用Dispose方法块

请参阅http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.71).aspx获取有关实现Dispose方法的详细信息,以及如何将其与Destructor(以及固有的垃圾收集器)结合使用的最佳实践