TPL Dataflow阻止等待GetRequestStreamAsync的死锁?

时间:2014-04-07 15:40:13

标签: c# httprequest async-await deadlock tpl-dataflow

我遇到了TPL数据流的问题,我似乎无法弄明白。我的代码将在15分钟到几个小时之间运行,直到死锁。我已经做了尽可能多的挖掘,我会尝试在这里发布。

另外,我一般都读到你shouldn't mix asynchronous and blocking code。如果我通过将我的TPL数据流代码隔离到Task.Run(Func<Task<bool>>)来做错了,请告诉我。否则,我不认为这是问题,因为它在自己的线程上运行。

我的数据流网络设置与this SO link完全相同,请参阅代码。

TransformBlock涉及许多不同的await。其中一个函数调用await httpRequest.GetRequestStreamAsync()。这似乎是发生死锁的地方,因为运行内存分析器会显示四个编译器生成的IAsyncStateMachine结构卡在内存中(例如<ExampleAsync>d__0),这些结构都表示在它被调用之前的状态

它还显示110个对象在TransformManyBlock(以及下一个BatchedJoinBlock)等待处理,并且只打开了267个HTTP连接(ServicePointManager.DefaultConnectionLimit已设置到512)。

检查GetRequestStreamAsync函数的源代码,发现至少有另一个线程是用Task.Run<>()创建的,这对我来说似乎没用。我以为我甚至可以自己调用FromAsync函数:

if (...)
{
    return Task.Run<Stream>(() => {
        TaskFactory<Stream> factory = Task<Stream>.Factory;
        WebRequest webRequest = this;
        WebRequest webRequest1 = this;
        return factory.FromAsync(
            new Func<AsyncCallback, object, IAsyncResult> (webRequest.BeginGetRequestStream), 
            new Func<IAsyncResult, Stream>(webRequest1.EndGetRequestStream), 
            null
        );
    });
}

可能是线程池已经用尽了吗?

我唯一的另一个线索是BatchedJoinBlock可能会占用资源,因为即使每个资源都已完成,它们也永远不会被处理掉 - 这导致我想要继续执行BatchedJoinBlock.Completion任务一个将在完成后取消联系的人。 (将MaxNumberOfGroups设置为1似乎没有这样做。)我相信有将近4000个BatchedJoinBlock徘徊。

我很难过。如果某些内容超时,则会捕获异常并将其传递到Exception的{​​{1}}目标。显然,情况并非如此。

0 个答案:

没有答案