[英]Deconstructor, Dispose don't know what to use
我的程序遇到了一个小问题。 我有一个带有Socket的类和一些声明的变量。
现在,当我离开定义类的页面时,
Class someclass = new class;
我希望该类被“销毁”,以便可以在另一页上使用相同的端口/ ip打开一个新的套接字。 (现在,端口和ip地址似乎已被我不解构/处理/ gc的类锁定)
因为我有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 thats,因为我已经尽力尝试实现它,但是效果不佳。 * /
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;
我希望这会有所帮助,以便你们可以帮助我:)
与C ++相比,.NET不允许显式销毁由垃圾收集器分配的实例(作为通过垃圾收集器分配的类型的实例的成员的类和装箱的值类型/值类型)。 这是因为垃圾收集器会在您认为必要时(定时间隔,内存压力等)进行清理。 如果需要在现场释放资源,则需要显式调用方法。 您可以将此方法命名为Cleanup。 .NET已经带有一个很好采用的模式。 方法名称是Dispose。 (您可以使用零参数和无效返回类型来实现Dispose方法,或者仅实现IDisposable接口。将该方法命名为'Dispose'而不是'Cleanup'可以为您提供更好的工具支持,并允许使用using语句在其中,您定义了应在其中使用实例的范围,并在范围块的末尾自动调用Dispose方法。
请参阅http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.71).aspx,以获取有关实现Dispose方法的详细信息以及如何将其与Destructor结合使用的最佳实践(本质上是垃圾收集器)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.