它是可以接受不调用Dispose()一个TPL任务对象? [英] Is it considered acceptable to not call Dispose() on a TPL Task object?

查看:184
本文介绍了它是可以接受不调用Dispose()一个TPL任务对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想触发一个任务在后台线程中运行。我不想伺候任务的完成。

I want to trigger a task to run on a background thread. I don't want to wait on the tasks completion.

在.NET 3.5中我会做这样的:

In .net 3.5 I would have done this:

ThreadPool.QueueUserWorkItem(d => { DoSomething(); });

在.NET 4的TPL是建议的方式。我看到建议的常见模式是:

In .net 4 the TPL is the suggested way. The common pattern I have seen recommended is:

Task.Factory.StartNew(() => { DoSomething(); });

不过, StartNew() 方法返回一个<一个href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx"><$c$c>Task对象,它实现了的IDisposable 。本 似乎是由人谁推荐这种模式被忽视。在 Task.Dispose()MSDN文档 法说:

However, the StartNew() method returns a Task object which implements IDisposable. This seems to be overlooked by people who recommend this pattern. The MSDN documentation on the Task.Dispose() method says:

总是调用Dispose你释放你的最后一个引用到任务之前。

"Always call Dispose before you release your last reference to the Task."

您不能调用处理一个任务,直到它完成,所以有主线程等待和呼叫处理会破坏上做摆在首位后台线程的地步。此外,还有似乎并不被认为可用于清除所有已完成的/完成的事件。

You can't call dispose on a task until it is completed, so having the main thread wait and call dispose would defeat the point of doing on a background thread in the first place. There also doesn't seem to be any completed/finished event that could be used for cleanup.

在任务类的MSDN页面没有对此进行评论,这本书临C#2010 ...建议相同的模式,不作任何评论任务处理。

The MSDN page on the Task class doesn't comment on this, and the book "Pro C#2010..." recommends the same pattern and makes no comment on task disposal.

我知道,如果我只是离开它的终结会赶上这到底,但是这是怎么回事回来,咬我,当我在做很多火灾放大器;忘了任务,像这样和终结器线程被淹没?

I know if I just leave it the finalizer will catch it in the end, but is this going to come back and bite me when I'm doing lots of fire & forget tasks like this and the finalizer thread gets overwhelmed?

所以,我的问题是:

  • 是不是可以接受的不叫的Dispose()工作类在这种情况下?如果是这样,为什么,是有风险/后果?
  • 是否有讨论这个问题的任何文档?
  • 或者是有处置的工作对象的适当方式,我已经错过了?
  • 或者是有做火与放大器的另一种方式;与TPL忘了任务?
  • Is it acceptable to not call Dispose() on the Task class in this case? And if so, why and are there risks/consequences?
  • Is there any documentation that discusses this?
  • Or is there an appropriate way of disposing of the Task object that I've missed?
  • Or is there another way of doing fire & forget tasks with the TPL?

推荐答案

有一个关于这个<一个讨论href="http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/7b3a42e5-4ebf-405a-8ee6-bcd2f0214f85"相对=nofollow>在MSDN论坛的。

斯蒂芬Toub,微软PFX团队的成员有这样一段话:

Stephen Toub, a member of the Microsoft pfx team has this to say:

Task.Dispose存在因任务   潜在的包裹事件句柄   用在任务等待时   完成后,在事件中等待   线程实际上已经阻止(如   相对于纺纱或可能   执行它的等待任务)。   如果你正在做的是使用   延续,该事件句柄将   从来没有被分配
  ...
  它可能更依赖于定稿处理后事。

Task.Dispose exists due to Task potentially wrapping an event handle used when waiting on the task to complete, in the event the waiting thread actually has to block (as opposed to spinning or potentially executing the task it's waiting on). If all you're doing is using continuations, that event handle will never be allocated
...
it's likely better to rely on finalization to take care of things.

更新(2012年10月)
斯蒂芬Toub已经发表了一篇博客题为我是否需要处置任务?这给一些细节,并解释在.net 4.5。

Update (Oct 2012)
Stephen Toub has posted a blog titled Do I need to dispose of Tasks? which gives some more detail, and explains the improvements in .Net 4.5.

在概括:你并不需要处置任务对象99%的时间

In summary: You don't need to dispose of Task objects 99% of the time.

有两个主要原因处置的对象:以释放非托管资源及时,确定的方式,并避免运行对象的终结的成本。这些都不适用于工作大部分的时间:

There are two main reasons to dispose an object: to free up unmanaged resources in a timely, deterministic way, and to avoid the cost of running the object's finalizer. Neither of these apply to Task most of the time:

  1. 作为的.Net 4.5,只有时间工作分配内部等待句柄(在任务的唯一非托管资源)对象是当你明确使用的 IAsyncResult.AsyncWaitHandle 工作
  2. 工作对象本身没有终结;手柄本身包装在一个对象与终结,所以,除非它的分配,没有终结运行。
  1. As of .Net 4.5, the only time a Task allocates the internal wait handle (the only unmanaged resource in the Task object) is when you explicitly use the IAsyncResult.AsyncWaitHandle of the Task, and
  2. The Task object itself doesn't have a finalizer; the handle is itself wrapped in an object with a finalizer, so unless it's allocated, there's no finalizer to run.

这篇关于它是可以接受不调用Dispose()一个TPL任务对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆