1

以下を考えると:

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace CancelAsyncFileReadFailure {
    class Program {
        static void Main( string[ ] args ) {
            Console.WriteLine( Foo( ).Result );
            Console.ReadLine( );
        }

public static async Task<TaskStatus> Foo( ) {
    byte[] bar = new byte[192000]; //Some arbitrarily significant number...
    using ( FileStream FS = new FileSTream( @"Path/To/WarAndPeace.txt", FileMode.Open ) ){
        CancellationTokenSource CTS = new CancellationTokenSource( );       
        Task T = FS.ReadAsync( bar, 0, 192000, CTS.Token );
        CTS.Cancel( );      
        await T;
        return T.Status;
    }
}

T常に終了して戻りますRanToCompletion

私のユースケースは、いつでも開いたり閉じたりできるデバイスから読み取っているという点で、やや複雑です (したがって、ファイルから直接読み取るのではなく、安全なファイルハンドルから読み取っています。ただし、結果はこのケースと私の実際のユースケースの両方)。

FileStream.ReadToAsync( ) を中断 (キャンセル) したい。

現在の場所で読み取りを停止し、すぐにキャンセルするようにするにはどうすればよいですか?

4

3 に答える 3

3

わかりました、ここでより良い答えを出してください。

でファイルを開く必要がありますFileOptions.Asynchronous。そうしないと、FileStream真のキャンセルが実装されずTask、呼び出し時にトークンがキャンセルされた場合にのみキャンセルが返されますReadAsync

于 2015-12-17T01:35:29.970 に答える
1

ウィル、コーリーの以前の答えは、実際には大したことではありませんでした。キャンセルは、安全なときに行う必要があります。ストリーム読み取りの場合、そのようなポイントは読み取りが実際に開始される前だけです。Positionストリーム読み取り要求が途中でキャンセルされた場合、キャンセルされたタスクが実際に完了すると、ストリームはどうなると思いますか? の場合はロールバックしても問題ないかもしれませんがFileStream、前方のみのストリームはどうでしょうか? ReadAsync前のタスクがキャンセル状態に移行した直後に別のタスクをスケジュールしたい場合はどうすればよいでしょうか? ドロップされたデータ チャンクとひどい破損が発生します。これは実際、Microsoft 側の賢明な設計のように思えます。バッファサイズを小さくして呼び出しますReadAsyncループで-その後、目的のキャンセルセマンティクスが得られます。

于 2015-12-17T01:40:38.907 に答える
1

キャンセルはベスト エフォートです。操作を実際にキャンセルできる場合にのみ発生します。

ここで考えられる 2 つのケースは、ファイルシステムのキャッシュにヒットした場合です。この場合、読み取りはすぐに同期的に完了するか、I/O 要求が既にディスクに送信されています。

于 2015-12-17T01:27:45.700 に答える