gpt4 book ai didi

c# - 有延迟的链接任务

转载 作者:太空狗 更新时间:2023-10-29 20:27:01 24 4
gpt4 key购买 nike

我需要跟踪一个任务并可能在延迟一段时间后将另一个任务排队,所以我想做的事情看起来像这样:

private Task lastTask;

public void DoSomeTask()
{
if (lastTask == null)
{
lastTask = Task.FromResult(false);
}
lastTask = lastTask.ContinueWith(t =>
{
// do some task
}).ContinueWith(t => Task.Delay(250).Wait());
}

我的问题是,如果我做这样的事情,创建可能很长的任务链是旧任务会被处置还是它们最终会永远坚持下去,因为 ContinueWith 将最后一个任务作为一个参数(所以它是一个闭包)。如果是这样,我如何在避免此问题的同时链接任务?

有更好的方法吗?

最佳答案

Task.Delay(250).Wait()

当您使用 Wait 时,您知道您做错了什么在您尝试使其异步的代码中。这是一个无所事事的浪费线程。

下面的会好很多:

lastTask = lastTask.ContinueWith(t =>
{
// do some task
}).ContinueWith(t => Task.Delay(250)).Unwrap();

ContinueWith返回 Task<Task> , 和 Unwrap call 把它变成 Task这将在内部任务完成时完成。

现在,为了回答您的问题,让我们看一下编译器生成的内容:

public void DoSomeTask()
{
if (this.lastTask == null)
this.lastTask = (Task) Task.FromResult<bool>(false);
// ISSUE: method pointer
// ISSUE: method pointer
this.lastTask = this.lastTask
.ContinueWith(
Program.<>c.<>9__2_0
?? (Program.<>c.<>9__2_0 = new Action<Task>((object) Program.<>c.<>9, __methodptr(<DoSomeTask>b__2_0))))
.ContinueWith<Task>(
Program.<>c.<>9__2_1
?? (Program.<>c.<>9__2_1 = new Func<Task, Task>((object) Program.<>c.<>9, __methodptr(<DoSomeTask>b__2_1))))
.Unwrap();
}

[CompilerGenerated]
[Serializable]
private sealed class <>c
{
public static readonly Program.<>c <>9;
public static Action<Task> <>9__2_0;
public static Func<Task, Task> <>9__2_1;

static <>c()
{
Program.<>c.<>9 = new Program.<>c();
}

public <>c()
{
base.\u002Ector();
}

internal void <DoSomeTask>b__2_0(Task t)
{
}

internal Task <DoSomeTask>b__2_1(Task t)
{
return Task.Delay(250);
}
}

这是用 dotPeek 在“告诉我所有的胆量”模式下反编译的。

看这部分:

.ContinueWith<Task>(
Program.<>c.<>9__2_1
?? (Program.<>c.<>9__2_1 = new Func<Task, Task>((object) Program.<>c.<>9, __methodptr(<DoSomeTask>b__2_1))))

ContinueWith函数被赋予一个单例委托(delegate)。因此,那里没有关闭任何变量。

现在,有这个函数:

internal Task <DoSomeTask>b__2_1(Task t)
{
return Task.Delay(250);
}

t这是对上一个任务的引用。注意到什么了吗?它从未被使用过。 JIT 会将这个本地标记为不可访问,GC 将能够清理它。启用优化后,JIT 将积极标记符合收集条件的局部变量,甚至可以在 GC 收集实例时执行实例方法,如果该实例方法不执行的话。 t 引用 this在剩下的代码中执行。

现在,最后一件事是 m_parent Task 中的字段类,这对您的场景不利。但只要你不使用 TaskCreationOptions.AttachedToParent你应该没事。您可以随时添加 DenyChildAttach额外安全和 self 记录的标志。

这是 function which deals with that :

internal static Task InternalCurrentIfAttached(TaskCreationOptions creationOptions)
{
return (creationOptions & TaskCreationOptions.AttachedToParent) != 0 ? InternalCurrent : null;
}

所以,你在这里应该是安全的。如果您想确定,请在长链上运行内存分析器,然后亲自看看。

关于c# - 有延迟的链接任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36991152/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com