在C#中是否有非托管资源?
我和朋友讨论了c#中的托管和非托管资源 据我的朋友说: 1.a)C#中的每个对象都是托管的,当我们在C#中编码时,没有什么比非托管对象或资源更好的了。非托管资源概念仅由C++来实现。 < 1)。我们在C++中是否有托管或非托管资源,我们需要明确地释放它。因为我们在C#中有自动垃圾收集器,所以我们不需要考虑管理资源 据我说: 2.a)如果我们没有非托管资源,那么为什么我们需要C#中的终结器或Dispose方法 2.b)垃圾收集器只包含有关已分配内存的信息,而不包含有关资源状态的信息。因此,我们需要使用dispose方法来释放C#中的资源 我需要帮助理解上面哪些参数是正确的,以及关于c#中非托管资源的信息,无论它们是否存在在C#中是否有非托管资源?,c#,garbage-collection,dispose,unmanagedresources,C#,Garbage Collection,Dispose,Unmanagedresources,我和朋友讨论了c#中的托管和非托管资源 据我的朋友说: 1.a)C#中的每个对象都是托管的,当我们在C#中编码时,没有什么比非托管对象或资源更好的了。非托管资源概念仅由C++来实现。 < 1)。我们在C++中是否有托管或非托管资源,我们需要明确地释放它。因为我们在C#中有自动垃圾收集器,所以我们不需要考虑管理资源 据我说: 2.a)如果我们没有非托管资源,那么为什么我们需要C#中的终结器或Dispose方法 2.b)垃圾收集器只包含有关已分配内存的信息,而不包含有关资源状态的信息。因此,我们需要
提前感谢。在.NET中创建的对象是托管代码,但您的对象可以包含对非托管资源的引用。垃圾收集器(GC)确保在不再需要托管堆上分配的任何内存后将其清除。 然而,尽管垃圾收集器在确保内存不泄漏方面非常出色,但它不知道需要释放的其他资源。例如,垃圾收集器不知道如何关闭文件句柄,也不知道如何使用诸如CoAllocTaskMem之类的API释放托管堆外部分配的内存 管理这些类型资源的对象必须确保在不再需要它们时释放它们。可以通过重写Stural.Objor的终结方法来实现这一点,它允许垃圾回收器知道对象希望参与它自己的清理(在C++中,您使用C++析构函数语法,~MyObjor,而不是直接重写方法)。如果一个类有一个终结器,那么在收集该类型的对象之前,垃圾收集器将调用该对象的终结器,并允许它清理它可能持有的任何资源 该系统的一个问题是,垃圾收集器不能确定地运行,因此,在对对象的最后一次引用消失后,对象可能在很长一段时间内无法最终确定。如果您的对象持有昂贵或稀有的资源,例如数据库连接,则这可能是不可接受的。例如,如果您的对象只有10个可用连接中的1个打开,那么它应该尽快释放该连接,而不是等待垃圾收集器调用finalize方法
为此,您应该实现一个IDisposable接口。阅读更多信息。在.net Framework下创建的每一件东西都是管理代码,因此内存仅由使用.net Framework manager创建的对象按框架使用 在.net框架之外创建的所有内容都是非托管代码。 当您想要释放hevy对象(如需要关闭文件或正在使用图形)并且想要释放与其相关的内存时,可以使用finalizer或dispose。您可以使用此方法。确实,在CLR中创建的所有对象都由CLR管理,因此您无需关心它们
但是,当您开始使用CLR外部的资源(例如COM对象或设备上的锁)时,您有责任释放这些资源。CLR无法为您执行此操作,但提供了
IDisposable
接口,允许您编写执行清理的代码。我们必须在.NET中处理非托管资源。一个很好的例子是与数据库的连接
我们必须显式关闭该非托管资源。这就是为什么我们在C#中有Dispose
。a)C#中的每个对象都是托管的,当我们在C#中编码时,没有什么比非托管的对象或资源更好的了。非托管资源概念仅来自C++。< /强>
这是不正确的。正如其他人所提到的,我们可以从C#(例如COM)之外获得非托管资源
但是,在C#中使用“非托管资源”而不访问非托管代码当然是可能的。这些资源可能不是严格意义上的垃圾收集的非托管资源,但作为开发人员,您必须处理清理这些资源。以线程为例:
class Foo
{
private Thread thread = new Thread(new ThreadStart(DoLotsOfWork));
private AutoResetEvent endThread = new AutoResetEvent(false);
private int sum = 0;
public Foo()
{
thread.Start();
}
public StopThread()
{
endThread.Set();
}
private void DoLotsOfWork()
{
while (!endThread.WaitOne(1000))
{
sum += 1;
}
}
}
static void Main(string[] args)
{
Foo foo = new Foo();
// Additional code...
foo.StopThread();
}
假设附加代码返回或抛出异常。如果不显式调用StopThread,执行DoLotsOfWork的线程将不会结束,并且您的进程可能不会退出
<强> B)C++中是否有托管或非托管资源,我们需要显式地释放它。由于C语言中有自动垃圾收集器,我们不需要考虑管理资源。
>绝对> <强>必须< /强>考虑C语言中的资源管理。正如您所建议的,这就是IDisposable存在的原因
考虑对上述代码的修改:class Foo : IDisposable
{
private bool disposed = false;
private Thread thread = new Thread(new ThreadStart(DoLotsOfWork));
private AutoResetEvent endThread = new AutoResetEvent(false);
private int sum = 0;
public Foo()
{
thread.Start();
}
public StopThread()
{
endThread.Set();
}
public Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void DoLotsOfWork()
{
while (!endThread.WaitOne(1000))
{
sum += 1;
}
}
private void Dispose(bool disposing)
{
if (!disposed && disposing)
{
StopThread();
disposed = true;
}
}
}
static void Main(string[] args)
{
using (Foo foo = new Foo())
{
// Additional code...
}
}
现在我们可以确定,无论附加代码做什么,Foo类创建的线程都将在进程退出之前停止。不,如果不使用非托管资源,就不可能编写C#程序。不可避免的是,C程序在100%非托管的操作系统上运行。如果使用文件,则使用操作系统资源。网络连接。一根线。控制台。等等,所有这些都是非常不受管理的资源 然而,这一事实在.NET中隐藏得相当清楚。框架库为这些本机对象提供了很好的包装类。文件流、套接字、线程、控制台等等。内存也是一种操作系统资源,垃圾收集器是它的包装器 在所有这些资源中,只有内存资源是真正自动管理的。其余的人都得到了奖章