locked
System.IO.StreamWriter.WriteAsync throws System.InvalidOperationException RRS feed

  • Question

  • Why does the following program throw System.InvalidOperationException on the line "return writer.WriteAsync(hugestring);"?


    using System.Threading.Tasks;
    using System.IO;
    
    namespace ConsoleApplication7
    {
        public class C
        {
            public Task WriteAsync()
            {
                var path = @"c:\temp\fail.txt";
                File.Delete(path);
                using (var file = File.OpenWrite(path))
                {
                    using (var writer = new StreamWriter(file))
                    {
                        string hugestring = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 ... 9999 ";  // SNIP! The original string was actually 48890 chars long!
                        return writer.WriteAsync(hugestring);
                    }
                }
            }
    
            public async void writeCaller()
            {
    
                await WriteAsync();
            }
    
        }
    
        class Program
        {
    
    
            static void Main(string[] args)
            {
                C c = new C();
                c.writeCaller();
            }
        }
    }
    

    Note that hugestring is actually many kilobytes long, but I've snipped out the contents for ease of display. Small (less than 2KB) hugestring values do not throw the exception.

    Friday, August 4, 2017 3:16 PM

All replies

  • You're closing the StreamWriter before the Task returned by WriteAsync has completed.

    In the future, please post the Exception.Message and the stack trace as well.

    Friday, August 4, 2017 8:32 PM
  • Hi PeterDMusial,

    Based on your description, I create a simple demo and reproduce your issue on my side. As a workaround, please use FileStream with custom sizeOfBuffer. like this:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CallAsyncMethod
    {
        public class C
        {
            public Task WriteAsync(string text)
            {
                var filePath = @"c:\temp\fail.txt";
                //File.Delete(path);
                //using (var file = File.OpenWrite(path))
                //{
                //    using (var writer = new StreamWriter(file))
                //    {
                //       return writer.WriteLineAsync(hugestring);
                //    }
                //}
                if (string.IsNullOrEmpty(filePath))
                    throw new ArgumentNullException("filePath");
                if (string.IsNullOrEmpty(text))
                    throw new ArgumentNullException("text");
                byte[] buffer = Encoding.Unicode.GetBytes(text);
                Int32 offset = 0;
                Int32 sizeOfBuffer = 4096;
                FileStream fileStream = null;
                try
                {
                    fileStream = new FileStream(filePath, FileMode.Append, FileAccess.Write,
                    FileShare.None, bufferSize: sizeOfBuffer, useAsync: true);
                    return fileStream.WriteAsync(buffer, offset, buffer.Length);
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    return null;
                    //Write code here to handle exceptions.
                }
                finally
                {
                    if (fileStream != null)
                        fileStream.Dispose();
                }
            }
    
            public async void writeCaller(string input)
            {
    
                await WriteAsync(input);
            }
    
        }
    
    
        class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    //List<string> list = new List<string>();
                    StringBuilder sb = new StringBuilder();
                    string hugestring = @"0 1 2 3 4 5 6 7 8 9 10 11 12 13 ... 9999";  // SNIP! The original string was actually 48890 chars long!
                    for (int i = 0; i < 500; i++)
                    {
                        sb.Append(hugestring);
                    }
    
                    C c = new C();
                    c.writeCaller(sb.ToString());
                    Console.ReadLine();
                    
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"There was an exception: {ex.ToString()}");
                }
            }
        }
    }
    

    Best regards,

    Cole


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, August 7, 2017 6:39 AM