Performing an await on an async operation does not use a new thread (unless the implementation explicitly starts one). It is possible to write an write to disk asynchronously without using a new worker thread. This article explains why in detail.
Task.Run, TaskFactory.StartNew and ThreadPool.QueueUserWorkItem will use a worker thread.
Contention, poor performance on ASP.NET
ASP.NET Core best practices
Tuning ASP.NET Core and avoiding large memory allocations
ASP.NET Thread usage
Tuning IIS 10
How the garbage collector causes random slowness
IO
IO Completion Threads in more detailIO Completion ports
Programming IOCP
IOCP and ASP.NET
Memory Management
Pooling memory buffers to avoid keep allocating memory on every requestMemory management and garbage collection
Using ArrayPool