C#从控制台应用程序读取/写入流异步

时间:2017-05-02 15:30:39

标签: c# multithreading asynchronous stream

我正在尝试编写一个控制台应用程序

  1. 从TcpClient接收已打开的流
  2. 从控制台获取输入并将其写入此Stream
  3. 收到回复并将其写入     控制台。
  4. 我尝试使用async / await进行这些操作,但不断获得异常。 这是我的代码:

       public void Main()
       {
             while(true)
            {
                WriteAsync(stream);
    
                ReadAsync(stream);
            }
        }
    
        private static void ReadAsync(Stream stream)
        {
            using (Stream console = Console.OpenStandardOutput())
             {
               CopyStream(stream, console);
             }
    
    
        }
    
        private static void WriteAsync(Stream stream)
        {
             using (Stream console = Console.OpenStandardInput())
             {
                 CopyStream(console, stream);
             }
    
        }
    
        private static async void CopyStream(Stream sourceStream, Stream targetStream)
        {
                 var buffer = new Byte[256];
                 int bytesRead = 0;
    
                 while((bytesRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                 {
                     await targetStream.WriteAsync(buffer, 0, bytesRead);
                 }
    
        }
    

    这是例外

    Unhandled Exception: System.NotSupportedException: Stream does not support reading.
       at System.IO.__Error.ReadNotSupported()
       at System.IO.Stream.BeginReadInternal(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state, Boolean serializeAsynchronously, Boolean apm)
       at System.IO.Stream.BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
       at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
       at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count)
       at TestBackend.Program.<CopyStream>d__3.MoveNext() in /home/slavskaya/avl_demonstrator/AVL_SCU/Tests/System/Backend/TestBackend/Program.cs:line 108
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.QueueUserWorkItemCallbackDefaultContext.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
       at System.Threading.ThreadPoolWorkQueue.Dispatch()System.NotSupportedException: Stream does not support reading.
       at System.IO.__Error.ReadNotSupported()
       at System.IO.Stream.BeginReadInternal(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state, Boolean serializeAsynchronously, Boolean apm)
       at System.IO.Stream.BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
       at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
       at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count)
       at TestBackend.Program.<CopyStream>d__3.MoveNext() in /home/slavskaya/avl_demonstrator/AVL_SCU/Tests/System/Backend/TestBackend/Program.cs:line 108
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.QueueUserWorkItemCallbackDefaultContext.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
       at System.Threading.ThreadPoolWorkQueue.Dispatch()System.NotSupportedException: Stream does not support reading.
       at System.IO.__Error.ReadNotSupported()
       at System.IO.Stream.BeginReadInternal(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state, Boolean serializeAsynchronously, Boolean apm)
       at System.IO.Stream.BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
       at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
       at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count)
       at TestBackend.Program.<CopyStream>d__3.MoveNext() in /home/slavskaya/avl_demonstrator/AVL_SCU/Tests/System/Backend/TestBackend/Program.cs:line 108
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.QueueUserWorkItemCallbackDefaultContext.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
       at System.Threading.ThreadPoolWorkQueue.Dispatch()
    Aborted
    

    我怀疑我刚刚锁定了流,或者在那里使用异步方法存在其他问题。

    所以我尝试创建不同的线程,但它们根本不工作

    Task.Run(() =>{
              while(true)
        {
           WriteAsync(stream);
        }
            });
      Task.Run(() =>{
              while(true)
        {
             ReadAsync(stream);
        }
            });
    

    我对异步和多线程都没什么经验,所以你可以指出我,这里的问题在哪里?

1 个答案:

答案 0 :(得分:2)

你不是等待每个操作,所以它们会重叠太多;你可能想要:

public async Task SomeAsyncMethod()
{
     while(true)
    {
        await WriteAsync(stream);

        await ReadAsync(stream);
    }
}

private static async Task ReadAsync(Stream stream)
{
    using (Stream console = Console.OpenStandardOutput())
     {
       await CopyStream(stream, console);
     }


}

private static async Task WriteAsync(Stream stream)
{
     using (Stream console = Console.OpenStandardInput())
     {
         await CopyStream(console, stream);
     }
}

然而,从非同步Main中调用它是令人烦恼的;只有Wait()

才是个好主意