Tag: 任务 并行库

有没有办法在没有抛出exception的情况下等待TPL任务?

我们中的一些人更喜欢以exception轻的方式编码。 但是,如果您等待任务并行库任务,并且任务抛出exception,它也会在调用线程上引发exception。 有没有(最好是标准的)方法来避免这种行为,只是在你找回exception时检查exception的响应?

关于Task.StartNew(Action ,Object)方法

我在这个页面上学习TPL,一个代码块让我很困惑。 我正在阅读此页面: 任务并行(任务并行库) 在一节中,它说下面的代码是正确的解决方案,因为循环中的lambda不能获得每次迭代后变异的值,而是最终值。 所以你应该在CustomData对象中包装“i”。 代码如下: class CustomData { public long CreationTime; public int Name; public int ThreadNum; } public class Example { public static void Main() { // Create the task object by using an Action(Of Object) to pass in custom data // to the Task constructor. This is useful when you need to […]

在任务中重新抛出exception(TPL)会丢失堆栈跟踪

我的代码重新抛出exception。 当我稍后从task.Exception读取exception时,它的stacktrace指向我重新抛出exception的位置(行n而不是行m,正如我所料)。 为什么会这样? TPL中的错误或更可能是我忽略的东西。 当我解决方法时,我可以将exception包装为新exception中的内部exception。 internal class Program { private static void Main(string[] args) { Task.Factory.StartNew(TaskMethod).ContinueWith(t => Console.WriteLine(t.Exception.InnerException)); Console.Read(); } private static void TaskMethod() { try { line m: throw new Exception(“Todo”); } catch (Exception) { line n: throw; } } }

TPL Dataflow:在保持秩序的同时设计并行性

我以前从未使用过TPL,所以我想知道是否可以用它完成:我的应用程序从很多帧创建一个gif图像动画文件。 我从一个Bitmap列表开始,它代表了gif文件的帧,需要为每个帧执行以下操作: 在框架上绘制一些文本/位图 裁剪框架 调整框架大小 将图像缩小为256色 显然,这个过程可以对列表中的所有帧并行完成,但是对于每个帧,步骤的顺序必须相同。 之后,我需要将所有帧写入gif文件。 因此,需要以与原始列表中相同的顺序接收所有帧。 最重要的是,此过程可以在第一帧准备就绪时开始,无需等到所有帧都被处理完毕。 这就是情况。 TPL Dataflow适合这个吗? 如果是的话,任何人都可以给我一个关于如何设计tpl块结构以反映上述过程的正确方向的提示吗? 与我发现的一些样品相比,这对我来说似乎相当复杂。

并行代码可扩展性差

最近我一直在分析我的并行计算如何实际加速16核处理器。 我得出的一般公式 – 你得到的每个核心速度越慢的线程就越让我感到尴尬。 以下是我的CPU负载和处理速度的图表: 因此,您可以看到处理器负载增加,但速度增加得慢得多。 我想知道为什么会发生这样的影响,以及如何得到不可伸缩行为的原因。 我已确保使用服务器GC模式 。 一旦代码不做任何事情,我就确保我正在并行化适当的代码 从RAM加载数据(服务器有96 GB的RAM,不应该触发交​​换文件) 执行不复杂的计算 在RAM中存储数据 我仔细分析了我的应用程序并发现没有瓶颈 – 看起来每个操作随着线程数的增长而变慢。 我被困了,我的情景出了什么问题? 我使用.Net 4任务并行库。

在TPL中返回一个空的静态任务是一种不好的做法?

有些情况下,我希望有条件地运行任务。 我使用某种类似的扩展方法: public static class MyTaskExtension{ private static Task theEmptyTask = Task.Factory.StartNew(() => {}); //This is the question public static Task ContinueWith(this Task task, Task continuationTask, Func condition) { if condition(){ … do the work } return theEmptyTask; } } 我的期望是,theEmptyTask已经完成,所以基本上如果我不想做任何事情我只返回这个任务,而不是null或一个新的空任务。 我觉得这种方法应该有一些小问题。 有人能看到吗?

任务取消exception(ThrowForNonSuccess)

这是这个问题的延续: 多任务延续 我在答案中更改了我的代码,但是现在我在尝试运行任务时收到TaskCancelledExceptions 。 public virtual async Task RunAsync(TaskWithProgress task) { Show(); TaskIsRunning(); await SetCompletedHandler(TaskComplete()); await SetCancelledHandler(TaskCancelled()) await SetFaultedHandler(TaskFaulted()); await task; Close(); } 但是以下代码没有。 我有点卡住为什么。 public virtual Task RunAsync(TaskWithProgress task) { Show(); TaskIsRunning(); SetCompletedHandler(TaskComplete()); SetCancelledHandler(TaskCancelled()) SetFaultedHandler(TaskFaulted()); return task; } 调用代码基本上涉及以下内容: await progressDialog.RunAsync(task); 编辑: 我没有在任何地方取消cancellationtoken ,所以我不明白为什么这会抛出exception。 三个SetXXXHandler()方法基本上执行以下具有不同延续状态的代码: task.ContinueWith(_ => action(), CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, this.Scheduler); 堆栈跟踪在这里: at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task […]

为什么LogicalCallContext无法与异步一起使用?

在这个问题中,Stephen Cleary接受的答案是LogicalCallContext无法与async一起正常工作。 他还在这个 MSDN主题中发布了它。 LogicalCallContext保持Hashtable存储发送到CallContext.LogicalGet / SetData的数据。 它只是这个Hashtable的浅层副本。 因此,如果您在其中存储可变对象,则不同的任务/线程将看到彼此的更改。 这就是Stephen Cleary的示例NDC程序(在MSDN线程上发布)无法正常工作的原因。 但是AFAICS,如果你只在Hashtable中存储不可变数据(可能通过使用不可变集合 ),那应该有效,让我们实现一个NDC。 然而,Stephen Cleary也在接受的答案中说: CallContext不能用于此。 Microsoft特别建议不要使用CallContext进行远程处理以外的任何操作。 更重要的是,逻辑CallContext不了解异步方法如何提前返回并稍后恢复。 不幸的是,该建议的链接已关闭(找不到页面)。 所以我的问题是,为什么不推荐这个? 为什么我不能以这种方式使用LogicalCallContext? 说它不理解异步方法是什么意思? 从调用者的POV来看,他们只是返回任务的方法,不是吗? ETA:另见其他问题 。 在那里,Stephen Cleary的答案说: 你可以使用CallContext.LogicalSetData和CallContext.LogicalGetData,但我建议你不要,因为当你使用简单的并行性时它们不支持任何类型的“克隆” 这似乎支持我的情况。 所以我应该能够建立一个NDC,这实际上是我需要的,而不是log4net。 我写了一些示例代码,它似乎工作,但仅仅测试并不总是捕获并发错误。 所以,由于其他post中有提示这可能不起作用,我仍然会问:这种方法有效吗? ETA:当我从下面的答案中运行斯蒂芬提出的复制品时,我没有得到错误的答案,他说我会,我得到正确的答案。 即使他说“这里的LogicalCallContext值总是”1“”,我总是得到0的正确值。这可能是因为竞争条件? 无论如何,我还没有在我自己的电脑上复制任何实际问题。 这是我正在运行的确切代码; 它只在这里打印“真实”,斯蒂芬说它至少应该在某些时候打印“假”。 private static string key2 = “key2”; private static int Storage2 { get { return (int) CallContext.LogicalGetData(key2); } set […]

我应该使用线程或任务 – 多客户端模拟

我正在编写一个客户端模拟程序,其中所有模拟客户端都针对服务器运行一些预定义的例程 – 这是一个在具有四个实例的azure中运行的Web服务器。 连接到服务器后,所有模拟客户端都运行相同的例程。 在任何时候我都想使用我的程序模拟300到800个客户端。 我的问题是:我应该创建N个客户端类实例并在N个不同的线程中运行它们吗? 要么 我应该使用任务库来做这些事情吗?

CancellationTokenSource的行为不符合预期

在这种情况下预期的是,如果用户通过按Enter键取消任务,则ContinueWith挂钩的另一个任务将运行,但事实并非如此,因为尽管在ContinueWith显式处理显然不是,但仍然抛出了AggregateException被执行。 有关下面的任何说明吗? class Program { static void Main(string[] args) { CancellationTokenSource tokensource = new CancellationTokenSource(); CancellationToken token = tokensource.Token; Task task = Task.Run(() => { while (!token.IsCancellationRequested) { Console.Write(“*”); Thread.Sleep(1000); } }, token).ContinueWith((t) => { t.Exception.Handle((e) => true); Console.WriteLine(“You have canceled the task”); }, TaskContinuationOptions.OnlyOnCanceled); Console.WriteLine(“Press any key to cancel”); Console.ReadLine(); tokensource.Cancel(); task.Wait(); } }