我有一个Bird
表单应用程序,我希望在每个Windows
上启动一个异步OnLoad
,该异步Task
被放置在下一个OnLoad
上。
使用Profiler
运行后,我发现每个OnLoad
之后对象数都越来越大。
我知道GC
不会在您调用Dispose
或将其设置为null
时释放内存。我应该覆盖终结器吗?
我也考虑过CancellationTokenSource
但我
表格
public class MyForm:Form
{
private Task task;
protected override OnLoad()
{
if(this.task!=null)
{
this.task.Dispose();
this.task=null;
}
this.task=Task.Run(()=>....);
}
}
带有令牌
public class MyForm:Form
{
private Task task;
private CancellationTokenSource=new CancellationTokenSource();
protected override OnLoad()
{
if(this.task!=null)
{
src.Cancel();
}
try
{
this.task=Task.Run(()=>....,src.Token);
}catch(TaskCancelledException ex)
{
return;
}
}
}
CancellationTokenSource
的问题在于,如您所见,我将在上一个Cancel
上呼叫Task
(在第二次OnLoad
呼叫中,我将处置第一个{{ 1}}),我不知道该问题是否会在Task
块中处理。
什么是尽快处置Try-Catch
对象的好方法?该Task
会在一定的时间间隔连续重新加载到计算机上,而我不想处理它,只需Form
答案 0 :(得分:1)
您不必根据自己的情况处理任务。它仅实现IDisposable,因为它可以分配一个WaitHandle(可抛弃):
在内部,Task可以分配一个WaitHandle,该WaitHandle可用于等待Task完成。 WaitHandle是IDisposable的,因为它在内部保留了IDisposable的SafeWaitHandle。 SafeWaitHandle会包装本机句柄资源:如果不处理SafeWaitHandle,最终将终结其终结器来清理打包的句柄,但与此同时,它的资源也不会被清理并且会对系统造成压力。然后,通过在Task上实现IDisposable,我们可以使关注于积极清理这些资源的开发人员能够及时进行清理。
现在,微软确实意识到这会造成混乱,因此他们进行了一些更改并提出了一些指导:
我们大大减少了分配Task的WaitHandle的可能性。我们重新实现了WaitAll和WaitAny,以便它们不依赖于Task的WaitHandle,并且我们避免在内部将其用于.NET 4.5中引入的任何新Task或与异步/等待相关的功能。因此,分配WaitHandle的唯一方法是,如果您明确要求Task的IAsyncResult.AsyncWaitHandle,那应该很少。这意味着,除非在极少数情况下,否则完全不需要处理任务。
和
我们已经使任务可用,即使它们已经被处置。现在,即使在任务处理完毕后,您也可以使用Task的所有公共成员,并且他们的行为将与处理之前一样。唯一不能使用的成员是IAsyncResult.AsyncWaitHandle,因为这是在处理Task实例时实际上要处理的内容;如果您在处理Task后尝试使用该属性,则该属性将继续引发ObjectDisposedException。这意味着您应该轻松自在地缓存已完成的任务,知道它们是纯粹的观察对象。此外,向前迈进,由于我们已经有了异步/等待和基于任务的异步模式,因此IAsyncResult的使用率应该会大大下降,即使对于IAsyncResult的继续使用,也很少使用其AsyncWaitHandle。
但是,基本建议是:
“否。不必费心处理任务。“通常很难找到一个合适的位置,这样做几乎没有理由,根据参考程序集,您甚至可能无法做到这一点。” >
(source)