【问题标题】:How to Asynchronously read MemoryStream如何异步读取 MemoryStream
【发布时间】:2016-05-12 08:05:41
【问题描述】:

我正在编写一个涉及 IronRuby 的应用程序。当我收到来自 ruby​​ 脚本的输出时,我想更新 UI 元素,因此我设置了以下内容:

var ScriptEngine engine = IronRuby.Ruby.CreateEngine();
MemoryStream outputStream = new MemoryStream();
engine.Runtime.IO.SetOutput(outputStream, Encoding.Default);

这会将 IronRuby 的输出重定向到名为 outputStream 的自定义流。但是,一旦流接收到新信息,我似乎无法弄清楚如何调用代码块。我怎么能做以下等效的事情?

outputStream.DataReceived += (sender, e) =>
{
    // assumes I passed in the Func `processing` to my method
    processing(e.Value);
};

谢谢!

【问题讨论】:

  • 您通常设置一个缓冲区byte[2048] buffer 并执行while(outputStream.Read()),这将连续循环读取2048 字节,并在流打开时继续这样做。看到这个answer
  • @CallumLinington 这不是异步的。
  • 也许如果我使用BackgroundWorker 我可以在新线程中运行它?
  • 你是什么意思异步,在另一个线程中运行或使用async/await,因为它们都可以通过流看到ReadAsync()来完成
  • 为什么要异步 MemoryStream 操作?您只是将字节从一个位置复制到另一个位置

标签: c# ironruby


【解决方案1】:

从任何流中异步读取的最简单方法是使用 ReadAsync,就像使用 Read 一样:

async Task MyMethod()
{
    ...
    byteArray = new byte[1024];
    int count = await memStream.ReadAsync(byteArray, 0, 1024);
    ...
}

通常,ReadAsync 是一个真正的异步调用,即它不使用在等待结果时阻塞的单独线程。它利用异步 I/O 完成端口将操作交给操作系统,只有当操作系统返回一些结果时才重新开始处理。

MemoryStream 可能有一个更简单的实现,尽管实际上不涉及 I/O。实际上,异步操作没有多大意义,因为 Read 只会将字节从流复制到缓冲区。

更新

在检查MemoryStream.ReadAsync 的来源后,ReadAsync 似乎只是直接调用Read 并返回带有读取字节数的Task<int>。这意味着字节复制仍然是同步完成的,但至少 MemoryStream 仍然可以在异步方法中使用。例如,可以在表单方法中使用,以避免在复制大缓冲区时阻塞 UI 线程。

这很有意义,因为简单地复制字节将比设置异步操作更快。

【讨论】:

  • 问题出现在另一个线程正在写入流时,而您正在读取它 - 在这种情况下,ReadAsync() 可能返回 0(指示流结束),即使另一个线程仍在写入它。这意味着您可能会在等待新数据的同时反复循环和调用ReadAsync(),并在有效的任意时间长度内反复返回 0。
  • @MatthewWatson 与异步操作无关。实际上,ReadAsync 只是调用 Read。您所描述的是一个发布/订阅问题。流不是发布/订阅实现,即使您使用Read,您所描述的内容对于任何流都将是一个问题。与您描述的最接近的是channels。但是,在它们成为 Core CLR 的一部分之前,您必须使用其他发布/订阅机制之一
  • @MatthewWatson 实际上,如果您只需将缓冲区从一个线程传递到另一个线程,那么 BlockingCollection 或 ConcurrentQueue 将比使用流好得多。
  • 同意——它也会影响非异步。我只是想提一下,因为它可能会影响 OP。也同意另一种方法对 OP 会更好。
  • @MatthewWatson 在这种情况下,流是该工作的错误工具。不过,OP 并没有询问高级场景。
猜你喜欢
  • 2021-09-24
  • 1970-01-01
  • 2014-10-11
  • 2018-11-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-30
  • 2020-08-20
  • 1970-01-01
相关资源
最近更新 更多