使用异步函数进行I / O绑定操作

时间:2019-07-02 02:41:29

标签: c# .net asynchronous

我正在阅读这份文档https://docs.microsoft.com/en-us/dotnet/csharp/async,其中说:

对于绑定到I / O的代码,您需要等待一个操作,该操作将在异步方法内部返回Task或Task。

我有两个问题:

针对I / O绑定代码的Q1-,是否表示我们需要使用Task.Factory.StartNew(..., TaskCreationOptions.LongRunning)TaskCompletionSource

Q2-我在下面编写了两个简单的控制台应用程序来模拟受I / O约束的代码,我的方法正确吗?

class Program  //use Task.Factory.StartNew
{
    static async Task Main(string[] args)
    {
        var task = ReadFile();
        Console.WriteLine("Do other work");
        int total = await task;
        Console.WriteLine($"Read {total} lines");
        Console.ReadLine();
    }

    static async Task<int> ReadFile()
    {
        return await Task.Factory.StartNew(new Func<int>(Read), TaskCreationOptions.LongRunning);
    }

    static int Read()
    {
        Thread.Sleep(5000); // simulate read operation
        return 9999;        // 9999 lines has been read
    }
}

class Program  // use TaskCompletionSource
{
    static void  Main(string[] args)
    {
        var awaiter = ReadFile().GetAwaiter();
        Console.WriteLine("Do other work");
        awaiter.OnCompleted(() => Console.WriteLine($"Read {awaiter.GetResult()} lines"));
        Console.ReadLine();
    }

    static Task<int> ReadFile()
    {
        var tcs = new TaskCompletionSource<int>();
        new Thread(() =>
        {
            tcs.SetResult(Read()); 

        }).Start();
        return tcs.Task;
    }

    static int Read()
    {
        Thread.Sleep(5000); // simulate read operation
        return 9999;        // 9999 lines has been read
    }
}

1 个答案:

答案 0 :(得分:3)

  

针对I / O绑定代码的Q1-,是否表示我们需要使用Task.Factory.StartNew(..., TaskCreationOptions.LongRunning)TaskCompletionSource

否。

这意味着您使用asyncawait

  

Q2-我在下面编写了两个简单的控制台应用程序来模拟受I / O约束的代码,我的方法正确吗?

否。

I / O本质上不是同步的,因此使用Thread.Sleep是I / O工作的不正确替代。 I / O本质上是异步的,因此正确的占位符是await Task.Delay

class Program  // use async/await
{
  static async Task Main(string[] args)
  {
    var task = ReadFileAsync();
    Console.WriteLine("Do other work");
    var result = await task;
    Console.WriteLine($"Read {result} lines");
    Console.ReadLine();
  }

  static async Task<int> ReadFileAsync()
  {
    await Task.Delay(5000); // simulate read operation
    return 9999;            // 9999 lines has been read
  }
}

在一般I / O情况下,为there is no thread。这就是为什么使用Thread.Sleep会丢掉所有内容的原因;当I / O不需要一个线程时,它将强制使用一个线程。