【问题标题】:Streams reading/writing causing deadlock?流读/写导致死锁?
【发布时间】:2015-01-29 01:04:08
【问题描述】:

我有如下代码sn-p,由多个线程并行执行:

private delegate Stream MyDelegate(string url);

private IAsyncResult BeginRequest(AsyncCallback callback, object state)
{
    return ((MyDelegate)QuerySync).BeginInvoke(url, callback, state);
}

private Stream EndRequest(IAsyncResult result)
{
    return ((MyDelegate)((AsyncResult)result).AsyncDelegate).EndInvoke(result);
}

private Stream QuerySync(string url)
{
    return (this.client).GetHttpWebResponse(url).GetResponseStream();
}

public async Task<Stream> GetResponseStream(string url){    
    using (Stream input = await Task<Stream>.Factory.FromAsync(BeginRequest, EndRequest, url, null).ConfigureAwait(false))
    {
        var output = new MemoryStream();
        await input.CopyToAsync(output).ConfigureAwait(false);
        output.Position = 0;
        return output;
    }
}

而且,由于某种原因,应用程序偶尔会在我的 GetResponseStream() 方法中停止(没有抛出异常,它只是永远挂起)。我环顾四周寻找可能的原因,发现在尝试从同一个 Stream 并行读取和写入时显然可能会发生死锁。问题是,在那种情况下,我实际上并没有从 same 流中读写(至少我是这么认为的)。因为我在调用 CopyToAsync 之前等待最近创建的写入输入流的任务结束(这显然在内部执行对该 Stream 的读取),所以只读在写入结束后开始。所以我不明白为什么这会导致死锁,因为我从来没有同时从同一个 Stream 读取和写入。

我不知道这是否重要,但附带说明一下,我的 QuerySync 方法是完全同步的,因为我用来获取响应的客户端目前不支持异步请求。

【问题讨论】:

  • 从多个线程同时从客户端的响应中获取流当然听起来是个坏主意。它不会期望客户端被设计为具有多个线程同时读取其响应流,这就是您正在做的事情。如果您想并行执行多个操作,请创建多个客户端,或者让一个线程读取数据并在将其放入数据结构后将其公开给多个线程。
  • @Servy:我试图简化代码,但我想我省略了一个重要要求(经过编辑以澄清这一点)——对 GetResponseStream 的每次调用都会提供一个传递给客户端的 URL,因此每次调用实际上对应于不同的响应,因此我无法读取一次数据然后将其公开。此外,创建多个客户端会破坏应用程序的性能,因为它会增加过多的开销。
  • 好吧,选择一个,一个“高性能”应用程序因为它不是线程安全而无法工作并死锁,或者一个“性能差”的应用程序实际上可以正常工作。
  • 我仍然不清楚死锁的原因是什么。
  • 您使用的类并非设计用于多线程的多线程。当你这样做时,大多数事情都可能发生,从死锁、异常、错误结果、世界崩溃等等。

标签: c# concurrency stream delegates deadlock


【解决方案1】:

您用于执行这些请求的客户端并非设计为可从多个线程并行访问。您需要创建多个客户端,这样它们就不会被单独的线程访问。

【讨论】:

    猜你喜欢
    • 2015-04-22
    • 1970-01-01
    • 2022-11-11
    • 2018-04-20
    • 2012-09-20
    • 2018-06-04
    • 2016-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多