延迟后调用方法(带参数)

时间:2013-11-20 19:41:50

标签: c#

我想将变量传递给延迟后运行的函数。我已经看到了关于如何做到这一点的类似问题(见下文)。我不认为这是我想要的,因为每次调用method1时,附加的匿名函数的数量会增加吗?我需要做的是删除任何现有的附加匿名函数,然后再添加新函数。但我不认为这是可能的。有没有办法在延迟后调用方法,但每次传递一个新的变量值?

using System.Timers;

myTimer = new Timer();
myTimer.Interval = 3000;
myTimer.AutoReset = false;

public void method1(int var1){
    myTimer.Elapsed += delegate { doSomething(var1); };
    myTimer.Start();
}

public void doSomething(int arg1){...}

更新

基本上每当method1运行时,我希望在3秒后发生一些事情,我需要传入一个可能每次都有变化的参数。

我不认为我可以使用字段来存储变量,因为在第一个计时器到期之前可能会多次调用method1。即可能有几个qued up。例如。在某个时间点,'doSomething'等待发生的问题可能是......

doSomething(3)
doSomething(7)
doSomething(1)

它只是在测试平台中使用,method1将被调用不超过50次。我想要确保的是每个doSomething(var1)只被调用一次而不是每3秒调用一次。也就是说,每次调用doSomething时只会调用一个method1

这适用于Windows控制台应用。

3 个答案:

答案 0 :(得分:5)

使用TPL(& .Net 4.5),您可以执行以下操作:

public static class ActionExtensions
{
    public static async void DelayFor(this Action act, TimeSpan delay)
    {
        await Task.Delay(delay);
        act();
    }
}

//usage
Action toDo = () => doSomething(var1);
toDo.DelayFor(TimeSpan.FromSeconds(3));

...或者这对您的应用来说可能更简单:

static async void DoSomethingLater(int n)
{
    await Task.Delay(TimeSpan.FromSeconds(3));
    //DoSomething(n);
}

//usage
void Method1(int n)
{
    DoSomethingLater(n);
}

答案 1 :(得分:3)

使用System.Timers.Timer无法做到这一点。

使用System.Threading.Timer,您可以将userState对象传递给构造函数。然后,每个tick都将该对象传递给计时器回调。例如:

string Whatever = "foo";
System.Threading.Timer timer = 
    new System.Threading.Timer(MyTimerCallback, whatever, 100, 100);

void MyTimerCallback (object state)
{
    string theData = (string)state;
    // at this point, theData is a reference to the "Whatever" string.
    // do tick processing
}

如果需要,您可以扩展System.Timers.Timer,并添加一个属性来保存您的数据。类似的东西:

class DerivedTimer : System.Timers.Timer
{
    public string Foo { get; set; }
}

myTimer = new DerivedTimer();
myTimer.Interval = 3000;

public void methodRunRegularly(int var1){
    myTimer.Foo = "Foobar!";
    myTimer.Elapsed += doSomething;
    myTimer.Start();
}

public void doSomething(object sender, EventArgs e)
{
    var t = (DerivedTimer)sender;
    var foo = t.Foo;
    // do processing
}

sender参数中传递对计时器的引用。您可以强制转换它,然后引用初始化计时器时设置的Foo属性。

答案 2 :(得分:3)

这使用了Reactive Extensions(使用nuget包“rx-main”)。

运行延迟3秒的方法:

public void method1(int value)
{
    ThreadPoolScheduler.Instance.Schedule(
        TimeSpan.FromSeconds(3), () => doSomething(value));
}

这差不多就足够了!