Tag: task parallel library

如何从.NET 4.5中的并行任务中获益

我想使用.NET迭代器和并行Tasks / await?。 像这样的东西: IEnumerable Foo(IEnumerable source) { Parallel.ForEach( source, s=> { // Ordering is NOT important // items can be yielded as soon as they are done yield return ExecuteOrDownloadSomething(s); } } 不幸的是.NET无法原生地处理这个问题。 迄今为止@svick的最佳答案 – 使用AsParallel()。 奖励:任何实现多个发布者和单个订阅者的简单异步/等待代码? 订阅者将屈服,并且pubs将处理。 (仅核心库)

Task.WhenAny和Unobserved Exceptions

假设我有三个任务, a , b和c 。 这三个都保证在1到5秒之间的随机时间抛出exception。 然后我写下面的代码: await Task.WhenAny(a, b, c); 这将最终从任何一个任务故障中抛出exception。 由于没有try…catch这里,这个例外会冒泡到我的代码中的其他地方。 剩下的两个任务抛出exception会发生什么? 是不是这些未被观察到的exception,这将导致整个过程被杀死? 这是否意味着使用WhenAny的唯一方法是在try…catch块中,然后在继续之前以某种方式观察剩余的两个任务? 后续行动:我希望将答案同时应用于.NET 4.5 和 .NET 4.0以及Async Targeting Pack(尽管在这种情况下显然使用了TaskEx.WhenAny )。

CorrelationManager.LogicalOperationStack是否与Parallel.For,Tasks,Threads等兼容

有关背景信息,请参阅此问题: 任务并行库中的任务如何影响ActivityID? 该问题询问Tasks如何影响Trace.CorrelationManager.ActivityId 。 @Greg Samson用测试程序回答了他自己的问题,该程序显示ActivityId在Tasks的上下文中是可靠的。 测试程序在Task委托的开头设置一个ActivityId,hibernate以模拟工作,然后检查最后的ActivityId以确保它是相同的值(即它没有被另一个线程修改)。 该程序成功运行。 在研究线程,任务和并行操作的其他“上下文”选项(最终为日志提供更好的上下文)时,我遇到了Trace.CorrelationManager.LogicalOperationStack的一个奇怪问题(无论如何我都很奇怪)。 我在下面的问题中复制了我的“答案”。 我认为它充分描述了我遇到的问题(Trace.CorrelationManager.LogicalOperationStack显然已经损坏 – 或者什么 – 当在Parallel.For的上下文中使用时,但只有当Parallel.For本身包含在逻辑操作中时) 。 这是我的问题: Trace.CorrelationManager.LogicalOperationStack应该可以与Parallel.For一起使用吗? 如果是这样,如果逻辑操作已经与Parallel.For启动了,它是否会产生影响? 是否有一种“正确”的方式使用LogicalOperationStack与Parallel.For? 我能不同地对这个示例程序进行编码以使其“有效”吗? 通过“工作”,我的意思是LogicalOperationStack总是具有预期的条目数,并且条目本身是预期的条目。 我已经使用Threads和ThreadPool线程做了一些额外的测试,但是我必须返回并重试那些测试,看看我是否遇到了类似的问题。 我会说,看起来任务/并行线程和ThreadPool线程确实从父线程“inheritance”了Trace.CorrelationManager.ActivityId和Trace.CorrelationManager.LogicalOperationStack值。 这是预期的,因为CorrelationManager使用CallContext的LogicalSetData方法(而不是SetData)存储这些值。 请再次参考此问题,以获取我在下面发布的“答案”的原始背景: 任务并行库中的任务如何影响ActivityID? 另请参阅Microsoft的Parallel Extensions论坛上的这个类似问题(目前尚未得到解答): http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/7c5c3051-133b-4814-9db0-fc0039b4f9d9 [BEGIN PASTE] 请原谅我发布这个作为答案,因为它不是你的问题的真正答案,但是,它与你的问题有关,因为它处理CorrelationManager行为和线程/任务/等。 我一直在寻找使用CorrelationManager的LogicalOperationStack (和StartLogicalOperation/StopLogicalOperation方法)在multithreading场景中提供额外的上下文。 我拿了你的例子并稍微修改它以增加使用Parallel.For并行执行工作的能力。 另外,我使用StartLogicalOperation/StopLogicalOperation来括号(内部) DoLongRunningWork 。 从概念上讲, DoLongRunningWork每次执行时都会执行以下操作: DoLongRunningWork StartLogicalOperation Thread.Sleep(3000) StopLogicalOperation 我发现,如果我将这些逻辑操作添加到您的代码中(或多或少),所有逻辑操作都保持同步(始终是堆栈上预期的操作数,并且堆栈上的操作值始终为预期)。 在我自己的一些测试中,我发现并非总是这样。 逻辑操作堆栈正在“损坏”。 我能想到的最好的解释是当“子”线程退出时将CallContext信息“合并”回“父”线程上下文导致“旧”子线程上下文信息(逻辑操作)为“inheritance“由另一个兄弟姐妹线程。 问题也可能与Parallel.For显然使用主线程(至少在示例代码中,如编写)作为“工作线程”之一(或者在并行域中应该调用它们)之间的事实有关。 每当执行DoLongRunningWork时,就会启动一个新的逻辑操作(在开始时)并停止(在结束时)(即,将其推送到LogicalOperationStack并从中弹出)。 如果主线程已经有效的逻辑操作,并且DoLongRunningWork在主线程上执行,则启动新的逻辑操作,因此主线程的LogicalOperationStack现在具有两个操作。 DoLongRunningWork的任何后续执行(只要DoLongRunningWork的这个“迭代”在主线程上执行)将(显然)inheritance主线程的LogicalOperationStack(现在它有两个操作,而不仅仅是一个预期的操作)。 我花了很长时间才弄清楚为什么LogicalOperationStack的行为在我的示例中与我的示例的修改版本不同。 最后,我看到在我的代码中,我在一个逻辑操作中将整个程序括起来,而在我的测试程序的修改版本中,我没有。 […]

在Windows服务中执行任务循环的最佳方法

我有一种方法可以向我们的客户发送一些短信,如下所示: public void ProccessSmsQueue() { SmsDbContext context = new SmsDbContext(); ISmsProvider provider = new ZenviaProvider(); SmsManager manager = new SmsManager(context, provider); try { manager.ProcessQueue(); } catch (Exception ex) { EventLog.WriteEntry(ex.Message, EventLogEntryType.Error); } finally { context.Dispose(); } } protected override void OnStart(string[] args) { Task.Factory.StartNew(DoWork).ContinueWith( ??? ) } 所以,我有一些问题: 我不知道方法运行需要多长时间; 该方法可以抛出exception,我想在EventLog上编写 我希望每10分钟在循环中运行此方法, 但只能在最后一次执行完成后运行。 我怎么能做到这一点? 我想过使用ContinueWith() ,但我仍然对如何构建整个逻辑有疑问。

最佳实践LongRunning任务创建

对于需要使用.Net 4中的Task API运行的后台线程,这是一个很好的设计吗? 我唯一担心的是,如果我们要取消该任务,我将如何做到这一点? 我知道我可以将ProgramEnding设置为true但我知道Task API中有一个CancellationToken 。 这只是一个示例代码示例,以便一个线程将添加到集合中,另一个线程将从中删除。 任务设置为LongRunning,因为这需要在程序运行时连续运行 private void RemoveFromBlockingCollection() { while (!ProgramEnding) { foreach (var x in DataInQueue.GetConsumingEnumerable()) { Console.WriteLine(“Task={0}, obj={1}, Thread={2}” , Task.CurrentId, x + ” Removed” , Thread.CurrentThread.ManagedThreadId); } } } private void button1_Click(object sender, EventArgs e) { DataInQueue = new BlockingCollection(); var t9 = Task.Factory.StartNew(RemoveFromBlockingCollection , TaskCreationOptions.LongRunning); for (int […]

Task(System.Threading.Task)和Thread之间的区别

根据我的理解,Task和Thread之间的区别是任务发生在线程池中,而线程是我需要自己管理的东西..(并且该任务可以取消并返回到线程池中他的任务结束) 但在一些博客中,我读到如果操作系统需要创建任务并创建thread =>,那么创建(和销毁)任务将更容易。 有人可以解释为什么创建任务很简单那个线程? (或许我在这里遗漏了一些东西……)

async和await关键字不会导致创建其他线程吗?

我糊涂了。 一个或多个Task如何在一个线程上并行运行? 我对并行性的理解显然是错误的。 MSDN的比特我无法理解: async和await关键字不会导致创建其他线程。 异步方法不需要multithreading,因为异步方法不能在自己的线程上运行。 该方法在当前同步上下文上运行,并且仅在方法处于活动状态时才在线程上使用时间。 ..和: 在启动任务和等待任务之间,您可以启动其他任务。 其他任务隐式并行运行,但不会创建其他线程。

处理包装任务的有限并发级别任务调度程序(具有任务优先级)

我很难找到一个任务调度程序,我可以在其上安排优先级任务,但也可以处理“包装”任务。 它类似于Task.Run尝试解决的问题,但您无法为Task.Run指定任务计划Task.Run 。 我一直在使用Parallel Extensions Extras Samples中的QueuedTaskScheduler来解决任务优先级要求(也是本文的建议)。 这是我的例子: class Program { private static QueuedTaskScheduler queueScheduler = new QueuedTaskScheduler(targetScheduler: TaskScheduler.Default, maxConcurrencyLevel: 1); private static TaskScheduler ts_priority1; private static TaskScheduler ts_priority2; static void Main(string[] args) { ts_priority1 = queueScheduler.ActivateNewQueue(1); ts_priority2 = queueScheduler.ActivateNewQueue(2); QueueValue(1, ts_priority2); QueueValue(2, ts_priority2); QueueValue(3, ts_priority2); QueueValue(4, ts_priority1); QueueValue(5, ts_priority1); QueueValue(6, ts_priority1); Console.ReadLine(); } private […]

永远不会触发TaskScheduler.UnobservedTaskException事件处理程序

我正在阅读一本关于C#任务并行库的书,并有以下示例,但永远不会触发TaskScheduler.UnobservedTaskException处理程序。 任何人都可以给我任何线索,为什么? TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs eventArgs) => { eventArgs.SetObserved(); ((AggregateException)eventArgs.Exception).Handle(ex => { Console.WriteLine(“Exception type: {0}”, ex.GetType()); return true; }); }; Task task1 = new Task(() => { throw new ArgumentNullException(); }); Task task2 = new Task(() => { throw new ArgumentOutOfRangeException(); }); task1.Start(); task2.Start(); while (!task1.IsCompleted || !task2.IsCompleted) { Thread.Sleep( 5000 ); } […]

Web Api – 火与忘记

我有一个Web API的动作,我需要运行一些任务而忘记这个任务。 这就是我的方法现在的组织方式: public async Task DoSth() { await Task.Run(…); ….. //Do some other work } 事情是,显然它停在等待线等待它完成后才继续工作。 我需要“解雇并忘记”我是否应该在没有任何异步等待的情况下调用Task.Run()?