Tag: task parallel library

在示例代码中是否需要Task.WhenAll?

在下面的代码中,task1和task2彼此独立,可以并行运行。 以下两个实现有什么区别? var task1 = GetList1Async(); var task2 = GetList2Async(); await Task.WhenAll(task1, task2); var result1 = await task1; var result2 = await task2; 和 var task1 = GetList1Async(); var task2 = GetList2Async(); var result1 = await task1; var result2 = await task2; 为什么我要选择一个而不是另一个? 编辑:我想补充一点,返回类型的GetList1Async()和GetList2Async()方法是不同的。

重型I / O操作中的Parallel.ForEach与Async Forloop

我想比较两种理论情景。 为了这个问题,我简化了案件。 但基本上它是典型的生产者消费者情景。 (我专注于消费者)。 我有一个大的Queue dataQueue ,我必须传输给多个客户端。 所以让我们从更简单的情况开始: class SequentialBlockingCase { public static Queue DataQueue = new Queue(); private static List _destinations = new List(); /// /// Is the main function that is run in its own thread /// private static void Run() { while (true) { if (DataQueue.Count > 0) { string data = […]

在直接从调用另一个库返回任务的库中使用ConfigureAwait(false)是否有利?

这个问题的后续行动。 我有一个包含许多异步方法的库,可以轻量地包装HttpClient 。 实际上他们只是做了一些设置并直接返回从HttpClient调用返回的Task : public Task DoThingAsyc() { // do some setup return httpClient.DoThingAsync(); } 我在考虑是否将ConfigureAwait(false)添加到这些调用中。 流行的智慧似乎是“是的,总是在图书馆那样做”。 但在这种情况下,它会引入一些(可能是可忽略的)开销,因为ConfigureAwait返回一个ConfiguredTaskAwaitable ,需要将其包装回Task中,以便不更改方法签名。 当然不难编码: public async Task DoThingAsyc() { // do some setup return await httpClient.DoThingAsync().ConfigureAwait(false); } 我的问题是, ConfigureAwait(false)的效率优势是否可能超过此案例中引入的额外开销? 以上哪个例子被认为是更好的做法?

如何正确地重新抛出已经处于故障状态的任务的exception?

我有一个同步方法,除其他外,它检查待处理任务的状态并重新抛出其exception,如果有的话: void Test(Task task) { // … if (task.IsFaulted) throw task.Exception; // … } 这不会传播exception堆栈跟踪信息,并且对调试器不友好。 现在,如果Test是async ,它将不会像这样简单和自然: async Task Test(Task task) { // … if (task.IsFaulted) await task; // rethrow immediately and correctly // … } 问题:如何正确执行同步方法? 我想出了这个,但我不喜欢它: void Test(Task task) { // … if (task.IsFaulted) new Action(async () => await task)(); // … }

数据流与拆分工作到小作业,然后再次分组

我需要做这样的工作: 从数据库中获取Page对象 为每个页面获取所有图像并处理它们(IO绑定,例如,上传到CDN) 如果所有图像都成功完成,则将页面标记为在数据库中处理 由于我需要控制并行处理的页数,我决定使用TPL数据流: ____________________________ | Data pipe | | BufferBlock | | BoundedCapacity = 1 | |____________________________| | ____________________________ | Process images | | TransformBlock | | BoundedCapacity = 1 | | MaxDegreeOfParallelism = 8 | |____________________________| | ____________________________ | Save page | | ActionBlock | | BoundedCapacity = 1 | | MaxDegreeOfParallelism […]

实现返回Task的方法时的合同协议

在实现返回关于抛出exception的Task的方法时,是否存在MS“最佳实践”或合同协议? 这是在编写unit testing时出现的,我试图弄清楚我是否应该测试/处理这种情况(我认识到答案可能是“防御性编码”,但我不希望这是答案)。 即 方法必须始终返回一个Task,该Task应包含抛出的Exception。 方法必须始终返回一个Task,除非该方法提供无效参数(即ArgumentException)。 方法必须总是返回一个任务,除非开发人员变得流氓并做他/她想要的事情(jk)。 Task Foo1Async(string id){ if(id == null){ throw new ArgumentNullException(); } // do stuff } Task Foo2Async(string id){ if(id == null){ var source = new TaskCompletionSource(); source.SetException(new ArgumentNullException()); return source.Task; } // do stuff } Task Bar(string id){ // argument checking if(id == null) throw new ArgumentNullException(“id”) try{ return […]

下游的TPL数据流块如何获取源生成的数据?

我正在使用TPL Dataflow处理图像。 我收到处理请求,从流中读取图像,应用几个转换,然后将生成的图像写入另一个流: Request -> Stream -> Image -> Image … -> Stream 为此,我使用块: BufferBlock TransformBlock TransformBlock TransformBlock TransformBlock … writerBlock = new ActionBlock 问题是初始Request是包含创建结果Stream所需的一些数据以及此时我需要的一些其他信息。 我是否必须将原始Request (或其他一些上下文对象) writerBlock到所有其他块上的writerBlock ,如下所示: TransformBlock<Request,Tuple> TransformBlock<Tuple,Tuple> TransformBlock<Tuple,Tuple> … (这是丑陋的),或者有没有办法将第一个块链接到最后一个块(或者,推广到需要附加数据的块)?

任务不是垃圾收集

在下面的程序中,我希望任务能够得到GC,但事实并非如此。 我使用了一个内存分析器,它表明即使任务显然处于最终状态, CancellationTokenSource也会保存对它的引用。 如果我删除TaskContinuationOptions.OnlyOnRanToCompletion ,一切都按预期工作。 为什么会发生这种情况,我该怎么做才能防止它呢? static void Main() { var cts = new CancellationTokenSource(); var weakTask = Start(cts); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); Console.WriteLine(weakTask.IsAlive); // prints True GC.KeepAlive(cts); } private static WeakReference Start(CancellationTokenSource cts) { var task = Task.Factory.StartNew(() => { throw new Exception(); }); var cont = task.ContinueWith(t => { }, cts.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default); ((IAsyncResult)cont).AsyncWaitHandle.WaitOne(); […]

c#锁定并听取CancellationToken

我想使用锁或类似的同步来保护关键部分。 同时我想听一个CancellationToken。 现在我正在使用这样的互斥锁,但是互斥锁并没有那么好的性能。 我可以使用任何其他同步类(包括新的.Net 4.0)而不是互斥锁吗? WaitHandle.WaitAny(new[] { CancelToken.WaitHandle, _mutex}); CancelToken.ThrowIfCancellationRequested();

并行运行异步方法

我有一个异步方法GetExpensiveThing() ,它执行一些昂贵的I / O工作。 这就是我使用它的方式: // Serial execution public async Task<List> GetThings() { var first = await GetExpensiveThing(); var second = await GetExpensiveThing(); return new List() { first, second }; } 但由于这是一种昂贵的方法,我想并行执行这些调用。 我本以为移动等待会解决这个问题: // Serial execution public async Task<List> GetThings() { var first = GetExpensiveThing(); var second = GetExpensiveThing(); return new List() { await first, […]