2015-08-17 20 views
9

Tôi có một phương thức lấy FileStream làm đầu vào. Phương thức này đang chạy bên trong vòng lặp for.Làm thế nào để trả về một luồng từ một phương pháp, biết nó nên được xử lý?

private void UploadFile(FileStream fileStream) 
{ 
    var stream = GetFileStream(); 
    // do things with stream 
} 

Tôi có một phương pháp mà tạo ra và trả về FileStream:

private FileStream GetFileStream() 
{ 
    using(FileStream fileStream = File.Open(myFile, FileMode.Open)) 
    { 
     //Do something 
     return fileStream; 
    } 
} 

Bây giờ phương pháp đầu tiên ném một ObjectDisposedException khi tôi cố gắng để truy cập FileStream trở lại, có lẽ vì nó đã đóng cửa kể từ tôi sử dụng "using" để xử lý đúng luồng.

Nếu tôi không sử dụng "sử dụng" và thay vào đó sử dụng nó như sau, thì FileStream vẫn mở và vòng lặp tiếp theo của vòng lặp (hoạt động trên cùng một tệp) ném một ngoại lệ cho biết tệp đã được sử dụng:

private FileStream GetFileStream() 
{ 
    FileStream fileStream = File.Open(myFile, FileMode.Open); 
    //Do something 
    return fileStream; 
} 

Nếu tôi sử dụng một thử-cuối cùng khối, nơi tôi đóng dòng trong finally thì nó cũng ném ObjectDisposedException.

Làm cách nào để trả lại luồng tệp hiệu quả và đóng luồng?

+2

Bạn không thể đóng nó, không phải công việc của bạn. Sử dụng tên tốt. "Nhận" là không đủ để giúp các lập trình viên tìm ra rằng ông cần phải xử lý các dòng, sử dụng "Tạo" thay thế. –

Trả lời

16

Khi bạn trả lại IDisposable từ một phương pháp, bạn đang xuống hạng trách nhiệm xử lý nó cho người gọi của bạn. Do đó, bạn cần khai báo khối using xung quanh toàn bộ quá trình sử dụng luồng, trong trường hợp của bạn có thể kéo dài cuộc gọi UploadFile.

using (var s = GetFileStream()) 
    UploadFile(s); 
4

Nếu bạn có phương thức cần trả về luồng tệp đang mở thì tất cả người gọi của phương thức đó cần phải chịu trách nhiệm xử lý luồng trả về vì không thể xử lý luồng trước khi trả lại.

4

Vấn đề là đối tượng FileStream được xử lý ngay sau khi bạn thoát khỏi phương pháp GetFileStream(), để lại nó trong trạng thái không sử dụng được. Như câu trả lời khác đã chỉ ra, bạn cần phải loại bỏ các khối using từ phương pháp đó và thay vào đó đặt khối using xung quanh bất kỳ mã mà các cuộc gọi phương pháp này:

private FileStream GetFileStream() 
{ 
    FileStream fileStream = File.Open(myFile, FileMode.Open); 
    //Do something 
    return fileStream; 
} 

using (var stream = GetFileStream()) 
{ 
    UploadFile(stream); 
} 

Tuy nhiên, tôi muốn thực hiện việc này một bước xa hơn. Bạn muốn có cách bảo vệ luồng được tạo bởi GetFileStream() từ trường hợp lập trình viên cẩu thả có thể gọi phương thức không có khối using hoặc ít nhất bằng cách nào đó cho người gọi biết rằng kết quả của phương pháp này cần được đính kèm với khối using . Do đó, tôi khuyên bạn nên sử dụng:

public class FileIO : IDisposable 
{ 
    private FileStream streamResult = null; 

    public FileStream GetFileStream(string myFile) 
    { 
     streamResult = File.Open(myFile, FileMode.Open); 
     //Do something 
     return streamResult; 
    } 

    public void Dispose() 
    { 
     if (streamResult != null) streamResult.Dispose();   
    } 

} 

using (var io = FileIO()) 
{ 
    var stream = io.GetFileStream(myFile); 

    // loop goes here. 
} 

Lưu ý rằng bạn không nhất thiết phải tạo một lớp hoàn toàn mới cho việc này. Bạn có thể đã có một lớp thích hợp cho phương thức này, nơi bạn có thể chỉ cần thêm mã IDisposable. Điều chính là bạn muốn sử dụng IDisposable như một tín hiệu cho các lập trình viên khác mà mã này nên được gói với một khối using. Ngoài ra, điều này đặt bạn lên để sửa đổi các lớp để bạn có thể tạo đối tượng IDisposable của bạn một lần, trước khi vòng lặp, và có trường hợp lớp mới theo dõi tất cả mọi thứ bạn cần phải vứt bỏ ở cuối vòng lặp. Quay lại đầu trang ||||

+1

Đây là một câu trả lời tuyệt vờ[email protected] Joel bạn có muốn xây dựng một chút về cách 'IDisposable' được sử dụng như một tín hiệu cho các lập trình viên khác không? Làm thế nào để các lập trình viên khác biết khi instantiating lớp này mà họ nên quấn mã của họ vào một 'sử dụng' khối? – jrn

Các vấn đề liên quan