【问题标题】:C# Read/write stream async from console applicationC# 从控制台应用程序异步读取/写入流
【发布时间】:2017-05-02 15:30:39
【问题描述】:

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

  1. 从 TcpClient 接收打开的 Stream
  2. 从控制台获取输入并将其写入此 Stream
  3. 接收响应并将其写入 控制台。

我尝试对这些操作使用 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);
    }
        });

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

【问题讨论】:

  • 我注意到ReadAsync 方法将控制台的标准输出流作为sourceStream 传递给尝试从中读取数据的CopyStream 方法。因此,您正在尝试从输出流中读取数据。
  • @LucaCremonesi 你是对的,我已经解决了这个问题,但事实并非如此,因为应用程序似乎在“WriteAsync(stream)”调用时崩溃并且永远不会达到“ReadAsync”

标签: c# multithreading asynchronous stream


【解决方案1】:

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

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()

是个好主意

【讨论】:

  • 谢谢你的回答,是的,我有点困惑我应该在哪里等待操作完成,但我该如何真正调用SomeAsyncMethod?我的意思是当我用while循环调用这个SomeAsyncMethod时,实际上根本没有循环,这个方法立即退出,怎么回事?在我的梦想中,我想象 CopyStream 实际上永远不会退出并且会不断等待输入,至少来自 NetworkStream,因为从这个流中读取永远不会返回 0。
  • @Semant1ka async 的全部意义在于,一旦遇到第一个不完整的结果,它就会返回给调用者,其余的异步工作会在结果可用时继续进行.在异步结果上“等待”是不正常的(您应该改为“等待”),但在控制台 exe 的 Main 方法的情况下,这样做可能是必要的;你可以可能侥幸逃脱:SomeAsyncMethod().Wait();,但是......最终这是“同步而不是异步”,这有点尴尬
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-30
  • 2014-05-18
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多