2016-05-05 17 views
13

Tôi đã xem qua các câu dưới đây khi cố gắng xác định xem tôi đã sử dụng Stream phương pháp như ReadAsyncCopyToAsync một cách chính xác: C# 4.5 file read performance sync vs asynckhông đồng bộ/đang chờ và mở một FileStream?

Trong câu hỏi này, tôi đọc phần sau đây trong câu trả lời được chấp nhận:

Đáng chú ý nhất, kiểm tra "async" của bạn không sử dụng I/O không đồng bộ; với tệp luồng, bạn phải mở chúng một cách rõ ràng là không đồng bộ hoặc khác bạn chỉ đang thực hiện các thao tác đồng bộ trên một chuỗi nền.

Trong mã IO không đồng bộ của mình, ông đã sử dụng sau đây để mở FileStream 'không đồng bộ':

var file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true) 

Vì vậy, tôi đã tự hỏi nếu bạn có ý định sử dụng các phương pháp như CopyToAsync xem bạn có nên mở tiềm ẩn FileStream như trình bày ở trên ?, như trái ngược với làm một cái gì đó đơn giản như sau:

File.Open(filename, FileMode.Open) 

Đó là cách ví dụ i n các tài liệu thực tế cho CopyToAsync chứng tỏ mở tiềm ẩn FileStream: https://msdn.microsoft.com/en-us/library/hh159084(v=vs.110).aspx

Nếu nó không quan trọng mà con đường tiềm ẩn FileStream được mở ra, những gì hiện các useAsync tham số của các nhà xây dựng FileStream làm gì?

Trả lời

8

Vì vậy, tôi đã tự hỏi nếu bạn có ý định sử dụng các phương pháp như CopyToAsync cho dù bạn nên mở FileStream cơ bản như được hiển thị ở trên?

Có. Lý do chủ yếu là lịch sử.

Đầu tiên, trên Windows, HANDLEs (including file handles) must be opened/created explicitly with an asynchronous flag if you want to do asynchronous (OVERLAPPED) operations on them.

Tuy nhiên, the old Windows 95/98/ME line only supported asynchronous operations on serial port and IOCTL (device driver) handles. I/O không đồng bộ trên tệp đĩa không được hỗ trợ trên dòng nền tảng đó. Và the original .NET did support 98/ME, do đó, bản gốc FileStream vừa được sử dụng đồng bộ I/O. Tôi nghĩ rằng (nhưng không hoàn toàn chắc chắn) rằng APM methods (như FileStream.BeginRead) trên Win98/ME có thể chỉ được triển khai bằng cách sử dụng cái gọi là "asynchronous delegates" (chỉ thực hiện một phương thức đồng bộ như FileStream.Read trên chuỗi chủ đề chuỗi).

Vì vậy, đó là lý do lịch sử tại sao xử lý luồng tệp là không phải được mở bằng cờ không đồng bộ theo mặc định.

Đó là cách ví dụ trong tài liệu hướng dẫn thực tế cho thấy CopyToAsync

Thật không may, rất nhiều những ví dụ MSDN có chất lượng khá kém. Chúng ổn nếu bạn tiếp cận chúng từ quan điểm "đây là một ví dụ về cách gọi phương thức cụ thể này", nhưng không quá lớn so với quan điểm "đây là ví dụ về mã chất lượng sản xuất sử dụng phương pháp này".

1

trang web MSDN nói

useAsync Chỉ định liệu có nên sử dụng không đồng bộ I/O hoặc đồng bộ I/O. Tuy nhiên, lưu ý rằng hệ điều hành bên dưới có thể không hỗ trợ I/O không đồng bộ, vì vậy khi chỉ định đúng, tay cầm có thể được mở đồng bộ tùy thuộc vào nền tảng. Khi được mở không đồng bộ, các phương pháp BeginReadBeginWrite hoạt động tốt hơn trên các lần đọc hoặc viết lớn, nhưng chúng có thể chậm hơn nhiều đối với các lần đọc hoặc viết nhỏ. Nếu ứng dụng được thiết kế để tận dụng I/O không đồng bộ, hãy đặt tham số useAsync thành true. Sử dụng I/O không đồng bộ chính xác có thể tăng tốc các ứng dụng nhiều nhất là hệ số 10, nhưng việc sử dụng nó mà không cần thiết kế lại ứng dụng cho I/O không đồng bộ có thể làm giảm hiệu suất theo hệ số là 10.

+0

Vì vậy, nó không quan trọng đối với các phương thức IO không đồng bộ khác như CopyToAsync? –

+0

Có, quan trọng đối với các phương thức IO không đồng bộ khác như CopyToAsync. nhưng Thật không may, MSDN nói không quan trọng. –

6

Tôi đã tự hỏi nếu bạn có ý định sử dụng các phương pháp như CopyToAsync cho dù bạn nên mở FileStream cơ bản như được hiển thị ở trên, như trái ngược với làm một cái gì đó đơn giản như File.Open?

Tôi đã sử dụng ILSpy để dịch ngược và xem File.Open.

public static FileStream Open(string path, FileMode mode) 
{ 
    return File.Open(path, 
        mode, 
        (mode == FileMode.Append) 
         ? FileAccess.Write 
         : FileAccess.ReadWrite, 
        FileShare.None); 
} 

nào gọi này:

public static FileStream Open(string path, FileMode mode, FileAccess access, FileShare share) 
{ 
    return new FileStream(path, mode, access, share); 
} 

Và cụ thể FileStream constructor này đi trong false cho tham số useAsync. Vì vậy, có nó xuất hiện để có vấn đề. Tuy nhiên, bạn vẫn có thể gọi các API async và nó vẫn hoạt động như bạn mong đợi.

Như Hans passant khẳng định:

Các cơ bản CreateFile() cuộc gọi sau đó sử dụng các tùy chọn FILE_FLAG_OVERLAPPED. Điều này cho phép chồng lên nhau I/O, một cơ chế cho phép đọc và ghi không đồng bộ ở cấp winapi.

Lớp FileStream có bool _isAsync, và nó có nghĩa là "Nếu async IO không được hỗ trợ trên nền tảng này hoặc nếu FileStream này đã không được mở ra với FileOptions.Asynchronous.".

Một lần nữa, bạn vẫn nhận được Task đại diện cho hoạt động không đồng bộ như bạn mong muốn.

+1

Tại sao sử dụng trình dịch ngược khi [bạn thực sự có thể xem nguồn] (http://referencesource.microsoft.com/#mscorlib/system/io/file.cs,1a53662a82db3651)? – svick

+0

Nguồn tham khảo rất tuyệt và tôi luôn sử dụng nó, nhưng những gì đảm bảo là có cập nhật cho đến nay? Tôi thực sự không biết ... dù bằng cách nào cũng dẫn đến một câu trả lời. –

+0

Nó nói rằng nó cho thấy nguồn cho .Net Framework 4.6.1, điều đó sẽ đủ gần đây. – svick

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