我正在尝试为Action创建一个方便的扩展方法,以便在延迟后基本上运行该操作:到目前为止,我的扩展程序看起来像这样
public static void DelayAction(this Action DelayedAction, int millisecondDelay, CancellationToken Token)
{
Task t = Task.Factory.StartNew(() => { Thread.Sleep(millisecondDelay); }, Token, TaskCreationOptions.None, TaskScheduler.Default);
t.ContinueWith(_ => DelayedAction, Token, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
我有一个函数,我调用它反过来使用这些扩展
private void DelayTask(Action ActiontoDelay, int millisecondDelay)
{
ActiontoDelay.DelayAction(millisecondDelay, _TokenSource.Token);
}
我称之为:
DelayTask(() => { _SomeFunction(SomeArgs); }, 1500);
但这一切似乎都落到了一个整体而且行动从未触发过。我哪里错了?
编辑17-11-11 2300hrs:
我删除了通用扩展方法,因为它与此示例无关。
此处也发表评论,因为它没有在评论中清楚地格式化代码
如果不是通话
DelayTask(() => { _SomeFunction(SomeArgs); }, 1500);
我直接这样做:
Task t = Task.Factory.StartNew(() => { Thread.Sleep(1500); }, Token, TaskCreationOptions.None, TaskScheduler.Default);
t.ContinueWith(() => { _SomeFunction(SomeArgs); }, Token, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
它工作正常(对不起,如果有任何语法错误,我已经从内存中完成了)所以我相信我的问题是处理尼克巴特勒的答案躲过的行动
答案 0 :(得分:5)
您的延续将返回DelayedAction
委托,而不是调用它:
t.ContinueWith(_ => DelayedAction(), Token, ...
答案 1 :(得分:3)
如果任务不是强烈要求,我建议使用内置“延迟”功能的System.Threading.Timer,构造函数如下:
public Timer(
TimerCallback callback,
Object state,
int dueTime,
int period
)
MSDN:
dueTime 类型:System.Int32调用回调之前的延迟时间(以毫秒为单位)。指定Timeout.Infinite to 阻止计时器启动。指定零(0)以启动计时器 立即
!此外,您可以在施工阶段后更改此延迟。
public static void DelayAction<T>(
this Action<T> delayedAction,
T argument,
int millisecondDelay,
CancellationToken cancellationToken)
{
// Timeout.Infinite to disable periodic signaling.
var timer = new System.Threading.Timer(x =>
{
cancellationToken.ThrowIfCancellationRequested();
delayedAction.Invoke(argument);
},
null,
millisecondDelay,
Timeout.Infinite);
}
答案 2 :(得分:0)
当然你可以完成任务。问题是,你调用了TaskFactory的StartNew,immediatley开始你的任务。
以这种方式尝试 - 这应该有效:
public static void DelayAction<T>(this Action<T> DelayedAction, int millisecondDelay, CancellationToken Token)
{
var task = new Task(t => { Thread.Sleep(millisecondDelay); }, null, Token);
task.ContinueWith(t => DelayedAction, Token, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
task.Start();
}