动作延迟扩展方法不起作用

时间:2011-10-17 16:56:05

标签: c# multithreading extension-methods action task

我正在尝试为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()); 

它工作正常(对不起,如果有任何语法错误,我已经从内存中完成了)所以我相信我的问题是处理尼克巴特勒的答案躲过的行动

3 个答案:

答案 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();
}