none
一个异步回调的问题盼高手解惑 RRS feed

  • 问题

  • class Program
      {
    
        static byte[] buffer;
    
        static void Main(string[] args)
        {
          Thread.CurrentThread.Name = "main thread";
    
          Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
          using (System.IO.FileStream fs = new System.IO.FileStream("read.txt",System.IO.FileMode.Open,System.IO.FileAccess.Read,System.IO.FileShare.None,4096,true))
          {
            buffer= new byte[fs.Length];
            fs.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(HandleCallback), fs);
          }
    
          Console.ReadLine();
    
        }
    
        static void HandleCallback(IAsyncResult ar)
        {
    
          using (System.IO.FileStream fs = ar.AsyncState as System.IO.FileStream)
          {
            int numbers= fs.EndRead(ar);
            Console.WriteLine(System.Text.Encoding.UTF8.GetString(buffer,0,buffer.Length));
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
          }
        }
    
      }
    
    

     

    代码很简单,在运行以上代码前,您判断一下,fs.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(HandleCallback), fs);这一行中最后的fs出了using的作用域后,回调函数中的

    using (System.IO.FileStream fs = ar.AsyncState as System.IO.FileStream)

    得到的fs会不会是null?

    按理说fs出了using后,即销毁了这个对象,但是实际运行时,在回调函数中,可以拿到非null的fs.实在有些不解?

    是不是因为垃圾回收会在下次回收时才销毁这个对象呢?盼高手解惑.谢谢.

    2010年9月18日 10:32

答案

  • class Program
    
     {
    
    
    
      static byte[] buffer;
    
    
    
      static void Main(string[] args)
    
      {
    
       Thread.CurrentThread.Name = "main thread";
    
    
    
       Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    
       using (System.IO.FileStream fs = new System.IO.FileStream("read.txt",System.IO.FileMode.Open,System.IO.FileAccess.Read,System.IO.FileShare.None,4096,true))
    
       {
    
        buffer= new byte[fs.Length];
    
        fs.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(HandleCallback), fs);
    
       }
    
    
    
       Console.ReadLine();
    
    
    
      }
    
    
    
      static void HandleCallback(IAsyncResult ar)
    
      {
    
    
    
       using (System.IO.FileStream fs = ar.AsyncState as System.IO.FileStream)
    
       {
    
        int numbers= fs.EndRead(ar);
    
        Console.WriteLine(System.Text.Encoding.UTF8.GetString(buffer,0,buffer.Length));
    
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    
       }
    
      }
    
    
    
     }
    
    
    
    

     

    代码很简单,在运行以上代码前,您判断一下,fs.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(HandleCallback), fs);这一行中最后的fs出了using的作用域后,回调函数中的

    using (System.IO.FileStream fs = ar.AsyncState as System.IO.FileStream)

    得到的fs会不会是null?

    按理说fs出了using后,即销毁了这个对象,但是实际运行时,在回调函数中,可以拿到非null的fs.实在有些不解?

    是不是因为垃圾回收会在下次回收时才销毁这个对象呢?盼高手解惑.谢谢.

    fs对象的回收,不一定在出作用域以后,取决于GC的执行时间和策略。

    dispose()方法的调用,只是立即释放了使用的非托管资源,而这个对象的托管资源可能还在内存中。CLR viz C#提到过一个对象复苏的问题。

    我猜测这里有个时间差。


    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
     

    老徐的网站】:http://www.frankxulei.com/

    老徐的博客】:http://www.cnblogs.com/frank_xl/

    微软WCF中文技术论坛
    微软WCF英文技术论坛

    2010年9月20日 10:03
    版主

全部回复

  • 垃圾回收的条件是一个对象不再被任何地方引用.
    Love Your Neighbor as Yourself
    2010年9月19日 8:43
  • Dispose() will not clear any reference. It just close the file stream.
    成为 Microsoft V Dash了。。。 欢迎各位前辈同事在OCS加我
    2010年9月20日 0:22
    版主
  • 似乎好像没有出定义域啊:

     using (System.IO.FileStream fs = new System.IO.FileStream("read.txt",System.IO.FileMode.Open,System.IO.FileAccess.Read,System.IO.FileShare.None,4096,true))
          {
            buffer= new byte[fs.Length];
            fs.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(HandleCallback), fs);
          }

          Console.ReadLine();  //此处才跳出using块。

    2010年9月20日 3:12
    版主
  • 感谢大家的回复。请看这句。

    fs.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(HandleCallback), fs);

    这是在另一个线程中运行的。

    主线程继续执行下面的代码

     }

          Console.ReadLine();
    所在当运行到 } 后面时,已经出了这个作用域,垃圾回收应该给fs打了上需要回收的标记。

    2010年9月20日 6:45
  • class Program
    
     {
    
    
    
      static byte[] buffer;
    
    
    
      static void Main(string[] args)
    
      {
    
       Thread.CurrentThread.Name = "main thread";
    
    
    
       Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    
       using (System.IO.FileStream fs = new System.IO.FileStream("read.txt",System.IO.FileMode.Open,System.IO.FileAccess.Read,System.IO.FileShare.None,4096,true))
    
       {
    
        buffer= new byte[fs.Length];
    
        fs.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(HandleCallback), fs);
    
       }
    
    
    
       Console.ReadLine();
    
    
    
      }
    
    
    
      static void HandleCallback(IAsyncResult ar)
    
      {
    
    
    
       using (System.IO.FileStream fs = ar.AsyncState as System.IO.FileStream)
    
       {
    
        int numbers= fs.EndRead(ar);
    
        Console.WriteLine(System.Text.Encoding.UTF8.GetString(buffer,0,buffer.Length));
    
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    
       }
    
      }
    
    
    
     }
    
    
    
    

     

    代码很简单,在运行以上代码前,您判断一下,fs.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(HandleCallback), fs);这一行中最后的fs出了using的作用域后,回调函数中的

    using (System.IO.FileStream fs = ar.AsyncState as System.IO.FileStream)

    得到的fs会不会是null?

    按理说fs出了using后,即销毁了这个对象,但是实际运行时,在回调函数中,可以拿到非null的fs.实在有些不解?

    是不是因为垃圾回收会在下次回收时才销毁这个对象呢?盼高手解惑.谢谢.

    fs对象的回收,不一定在出作用域以后,取决于GC的执行时间和策略。

    dispose()方法的调用,只是立即释放了使用的非托管资源,而这个对象的托管资源可能还在内存中。CLR viz C#提到过一个对象复苏的问题。

    我猜测这里有个时间差。


    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
     

    老徐的网站】:http://www.frankxulei.com/

    老徐的博客】:http://www.cnblogs.com/frank_xl/

    微软WCF中文技术论坛
    微软WCF英文技术论坛

    2010年9月20日 10:03
    版主
  • 回收是回收  dispose 是dispose.

    dispose 不是标记回收 而是释放其中占用的所有非托管资源

     

    只要你还有任何一个变量可以访问fs 的引用    就绝对不会标记回收,也就是说那个代理中的fs不被设置为null 就绝对还存在一个disposed fs。

    这是基础概念, 希望lz不要在用错误的基础概念倒江湖啊。

     

     


    入了ipad,最近用ipad上论坛
    2010年9月20日 10:27
    版主