相关疑难解决方法(0)

.NET中管理单独(单个)线程上任务队列的最佳方式

我知道异步编程多年来已经发生了很多变化.我有点尴尬,我让自己在34岁时就生锈了,但我依靠StackOverflow让我加快速度.

我想要做的是在一个单独的线程上管理一个"工作"队列,但是这样一次只能处理一个项目.我想在这个线程上发布工作,它不需要将任何内容传递给调用者.当然,我可以简单地旋转一个新Thread对象并让它在一个共享Queue对象上循环,使用睡眠,中断,等待句柄等.但是我知道事情从那以后变得更好.我们有BlockingCollection,Task,async/ await,更不用提的NuGet包,可能抽象了很多的.

我知道"什么是最好的..."这些问题通常是不受欢迎的,所以我会通过说"目前推荐的是什么......"的方式来改进它,最好使用内置的.NET机制来完成这样的事情.但是如果第三方NuGet包简化了一堆东西,它也是如此.

我认为一个TaskScheduler固定最大并发度为1 的实例,但似乎现在可能没那么笨重的方法了.

背景

具体来说,我在这种情况下尝试做的是在Web请求期间排队IP地理定位任务.相同的IP可能会多次排队等待地理定位,但是任务将知道如何检测并尽快跳过,如果它已经解决了.但请求处理程序只是将这些() => LocateAddress(context.Request.UserHostAddress)调用抛入队列,让该LocateAddress方法处理重复的工作检测.我正在使用的地理位置API不喜欢被请求轰炸,这就是我想一次将它限制为单个并发任务的原因.但是,如果允许通过简单的参数更改轻松扩展到更多并发任务,那将是很好的.

.net c# concurrency asynchronous task-parallel-library

23
推荐指数
5
解决办法
4万
查看次数

任务并行库(或PLINQ)是否考虑了其他过程?

特别是,我正在寻找使用TPL来启动(和等待)外部进程.在决定启动另一个任务之前,TPL是否会查看总机器负载(CPU和I/O)(因此 - 在我的情况下 - 另一个外部进程)?

例如:

我有大约100个需要编码或转码的媒体文件(例如从WAV到FLAC或从FLAC到MP3).编码是通过启动外部进程(例如FLAC.EXE或LAME.EXE)完成的.每个文件大约需要30秒.每个进程主要是CPU绑定的,但那里有一些I/O. 我有4个内核,所以最糟糕的情况(通过将解码器传输到编码器中进行代码转换)仍然只使用2个内核.我想做点什么:

Parallel.ForEach(sourceFiles,
    sourceFile =>
        TranscodeUsingPipedExternalProcesses(sourceFile));
Run Code Online (Sandbox Code Playgroud)

这将启动100个任务(因此200个外部进程竞争CPU)?或者它会看到CPU忙,一次只做2-3次?

task-parallel-library

14
推荐指数
1
解决办法
2163
查看次数

管理TPL队列

我有一个运行扫描各种服务器的服务.有问题的网络可能很庞大(数十万个网络节点).

该软件的当前版本使用由我们设计的排队/线程架构,其工作但效率不高(尤其是因为作业可能会产生不能很好处理的子节点)

V2即将到来,我正在考虑使用TPL.它似乎应该是理想的选择.

我已经看到了这个问题,答案意味着TPL可以处理的任务没有限制.在我的简单测试中(旋转100,000个任务并将它们交给TPL),TPL很早就开始出现Out-Of-Memory异常(足够公平 - 特别是在我的开发盒上).

扫描需要不同的时间长度,但5分钟/任务是一个很好的平均值.

可以想象,对于庞大网络的扫描可能需要相当长的时间,即使在功能强大的服务器上也是如此.

我已经有了一个框架,允许扫描作业(存储在Db中)在多个扫描服务器之间分配,但问题是我应该如何将工作传递给特定服务器上的TPL.

我可以监控TPL队列的大小吗(如果它低于几百个条目,可以加满)吗?这样做有不利之处吗?

我还需要处理需要暂停扫描的情况.通过不向TPL提供工作比通过取消/重置可能已经部分处理的任务更容易做到这一点.

所有初始任务都可以按任何顺序运行.必须在父项开始执行后运行子项,但由于父项产生它们,这应该不是问题.孩子们可以按任何顺序跑步.因此,我目前正在设想将子任务写回Db而不是直接生成TPL.如果需要,这将允许其他服务器"偷窃".

有没有人以这种方式使用TPL的经验?我需要注意哪些方面的考虑因素?

parallel-processing multithreading .net-4.0 task-parallel-library

5
推荐指数
1
解决办法
8928
查看次数

如何尽快有效地发出数千个Web请求

我需要从C#控制台应用程序发出100,000个轻量级(即小的Content-Length)Web请求。我这样做的最快方法是什么(即在最短的时间内完成所有请求),我应该遵循哪些最佳实践?我无法解雇并忘记,因为我需要捕获响应。

大概我想使用asyncWeb请求方法,但是我想知道存储所有Task连续和编组的开销会产生什么影响。

内存消耗不是一个整体问题,目标是速度。

大概我也想利用所有可用的内核。

所以我可以做这样的事情:

Parallel.ForEach(iterations, i =>
{
    var response = await MakeRequest(i);
    // do thing with response
});
Run Code Online (Sandbox Code Playgroud)

但这不会让我比内核数量更快...

我可以:

Parallel.ForEach(iterations, i =>
{
    var response = MakeRequest(i);
    response.GetAwaiter().OnCompleted(() =>
    {
        // do thing with response
    });
});
Run Code Online (Sandbox Code Playgroud)

但是如何使我的程序在ForEach。握住所有TasksWhenAll荷兰国际集团他们觉得胀,是否有任何现有的模式或佣工有某种任务队列?

有什么方法可以使情况变得更好,如何处理节流/错误检测?例如,如果远程端点响应缓慢,我不想继续向其发送垃圾邮件

我了解我也需要这样做:

ServicePointManager.DefaultConnectionLimit = int.MaxValue
Run Code Online (Sandbox Code Playgroud)

还有什么需要的吗?

c# concurrency asynchronous

5
推荐指数
1
解决办法
414
查看次数