mscorlib.dll中出现“System.ArgumentException”类型的第一次机会异常

时间:2014-02-03 12:55:19

标签: c# ftp stream

  try
        {
            FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
            req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
            using (var resp = (FtpWebResponse)req.GetResponse())
            {
                Console.WriteLine(resp.WelcomeMessage);
            }
            FtpWebResponse res = (FtpWebResponse)req.GetResponse();
            Stream rs = res.GetResponseStream();
            StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
            Console.WriteLine(read1.ReadToEnd());
            Console.WriteLine("Directory is compleate,status(0)",
            res.StatusDescription);
            read1.Close();
            rs.Close();
        }
        catch (Exception e1)
        {
            Console.WriteLine(e1.Message);
        }

我试图通过C#访问ftp服务器。

但是,代码错误有例外:
A first chance exception of type "System.ArgumentException" occured in mscorlib.dll. Stream was not readable.

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

将所有IDisposable资源放在using(...) {...}中。技术可以防止 资源泄漏/关闭资源调用:

try {
  FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
  req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

  // Response: we're going to work wuth respose within "using" block only
  using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
    Console.WriteLine(resp.WelcomeMessage);

    // Reader: once again reader's opened once and called within using only
    using (StreamReader reader = new StreamReader(resp.GetResponseStream())) {
      Console.WriteLine(reader.ReadToEnd());
      Console.WriteLine("Directory is complete, status(0)", resp.StatusDescription);
    }
  }
catch (Exception ex) { // <- Bad idea to catch all possible exceptions without "throw;"
  Console.WriteLine(ex.Message);
}

答案 1 :(得分:0)

TLDR;处置FtpWebResponse对象的状态,因此您无法读取响应流。流已关闭。

反汇编FtpWebResponse:

public override void Close()
        {
            if (Logging.On)
            {
                Logging.Enter(Logging.Web, this, "Close", "");
            }
            if (this.HttpProxyMode)
            {
                this.m_HttpWebResponse.Close();
            }
            else
            {
                Stream responseStream = this.m_ResponseStream;
                if (responseStream != null)
                {
                    responseStream.Close();
                }
            }
            if (Logging.On)
            {
                Logging.Exit(Logging.Web, this, "Close", "");
            }
        }

您获得异常的原因是您正在阅读回复:

using (var resp = (FtpWebResponse)req.GetResponse())
{
    Console.WriteLine(resp.WelcomeMessage);
}

在下一行,您尝试再次将响应读入另一个变量:res

FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A

在该部分中,您还会对res.GetResponseStream()进行两次调用,但这与发生错误无关。即使您将其更改为:

,也会发生错误
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A

或者:

FtpWebResponse res = (FtpWebResponse)req.GetResponse();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A

发生错误的原因是FtpWebResponse对象的状态,它被处理掉;并拥有StatusCode = ClosingData。当我尝试在该状态下读取流时,我会收到您遇到的错误。在之前的使用块中,StatusCode = OpeningData

但是,如果你只想改变几行:

using (var resp = (FtpWebResponse)req.GetResponse())
{
    Console.WriteLine(resp.WelcomeMessage);
    Stream rs = res.GetResponseStream();
    StreamReader read1 = new StreamReader(rs);// prob A
    Console.WriteLine(read1.ReadToEnd());
    Console.WriteLine("Directory is compleate,status(0)", res.StatusDescription);
}

使用范围输入此内容时,StatusCode = OpeningData和流可用且可读。退出范围时,StatusCode = ClosingData和流将无法读取。

希望这是有道理的,如果我错了,请纠正我。 : - )

通过这些小的更改,您的代码将按预期运行。但是你应该研究@DmitryBychenko建议的模式。这样,您就可以访问所需范围内的资源,并在之后处理。