首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动作延迟扩展方法不起作用

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

Stack Overflow用户
提问于 2011-10-18 00:56:05
回答 3查看 836关注 0票数 4

我正在尝试为Action创建一个方便的扩展方法,以便在延迟后运行该操作:

代码语言:javascript
复制
    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());
    }

我调用了一个函数,该函数使用这些扩展

代码语言:javascript
复制
    private void DelayTask(Action ActiontoDelay, int millisecondDelay)
    {
        ActiontoDelay.DelayAction(millisecondDelay, _TokenSource.Token);
    } 

我这样称呼它:

代码语言:javascript
复制
    DelayTask(() => { _SomeFunction(SomeArgs); }, 1500);

但这一切似乎都落在了一个整体上,动作永远不会触发。我哪里错了?

编辑17:11-11:00:

我删除了泛型扩展方法,因为它与本例无关。

我还在这里发表了评论,因为它没有在评论中清楚地格式化代码

如果不是调用

代码语言:javascript
复制
DelayTask(() => { _SomeFunction(SomeArgs); }, 1500); 

我直接这样做:

代码语言:javascript
复制
Task t = Task.Factory.StartNew(() => { Thread.Sleep(1500); }, Token, TaskCreationOptions.None, TaskScheduler.Default); 
t.ContinueWith(() => { _SomeFunction(SomeArgs); }, Token, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); 

它工作得很好(抱歉,如果有任何语法错误,我已经根据记忆完成了),所以我认为我的问题在于对Nick Butler的答案所回避的Action的处理

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-10-18 01:36:05

您的延续将返回DelayedAction委托,而不是调用它:

代码语言:javascript
复制
t.ContinueWith(_ => DelayedAction(), Token, ...
票数 5
EN

Stack Overflow用户

发布于 2011-10-18 01:16:54

如果任务不是一个很强的需求,我建议使用System.Threading.Timer,它有内置的“延迟”功能,构造函数看起来像这样:

代码语言:javascript
复制
public Timer(
    TimerCallback callback,
    Object state,
    int dueTime,
    int period
)

MSDN

dueTime类型: System.Int32调用回调前的延迟时间,单位为毫秒。指定Timeout.Infinite以阻止计时器启动。指定零(0)可立即启动计时器。

!同样重要的是,您可以在构建阶段之后更改此延迟。

代码语言:javascript
复制
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);                        
        }  
票数 3
EN

Stack Overflow用户

发布于 2011-10-18 03:34:17

当然,你也可以通过任务来实现。问题是,您调用了TaskFactory的StartNew,它会立即启动您的任务。

试着这样做--这应该行得通:

代码语言:javascript
复制
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();
} 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7797001

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档