等待Threading.Timer回调函数结束

时间:2016-06-27 18:07:56

标签: c# multithreading timer callback

我启动了一个带回调函数的计时器。但是在这个回调函数中,我更改/初始化了一个静态对象,该对象在启动计时器后使用。

public class TimerExecute
{
    // Assume that the "Dog" class exist with attribute Name initialized in the constructor
    public static List<Dog> listDog = new List<Dog>();

    public void callbackFunct(String param) {

        // code...

        listDog.Add(new Dog("Bob"));

        // code...
    }

    public void Main() {
        // add dogs Bob each 10sec
        Timer addbobs = new Timer((e) => callbackFunct("arg"), null, 0, 10000);

        // return argumentoutofrange exception
        Console.WriteLine(listDog[0].name);
    }
}

当我使用静态var时,我有一个异常“参数超出范围异常”。我认为问题在于回调函数没有完成执行并且对象尚未初始化。

我试过这个解决方案,但这不起作用:

// add dogs Bob each 10sec
Timer addbobs = new Timer((e) => callbackFunct("arg"), null, 0, 10000);
WaitHandle h = new AutoResetEvent(false);
addbobs.Dispose(h);
Console.WriteLine(listDog[0].name);

但有了它,它的确有效:

Timer addbobs = new Timer((e) => callbackFunct("arg"), null, 0, 10000);
Thread.Sleep(2000);
Console.WriteLine(listDog[0].name);

我希望我的回调函数在下一个语句之前完成执行。 你有解决我的问题的方法吗?

上次编辑:是的我希望能够将参数传递给callbackFunct

2 个答案:

答案 0 :(得分:1)

这是我想出的。诀窍是传入AutoResetEvent,你必须自己在那个事件上调用Set(),这就是该方法已经完成的信号&#34; (实际上它只是表示方法被调用,无论方法是否完成)。因为看起来除了WaitHandle之外你还需要发送回调用的其他参数,所以我创建了一个类来封装它们。

        public void callbackFunct(object state)
        {
            var myParams = (CustomParametersWithWaitHandle)state;
            string name = myParams.Parameter1;
            AutoResetEvent wh = myParams.WaitHandle;
            // code...

            listDog.Add(new Dog(name));

            // code...

            wh.Set(); // signal that this callback is done
        }

        public void Main()
        {
            // add dogs Bob each 10sec
            AutoResetEvent wh = new AutoResetEvent(false);
            var myCustomParams = new CustomParametersWithWaitHandle(wh, "bob", 314);
            Timer addbobs = new Timer(new TimerCallback(callbackFunct), myCustomParams, 0, 10000);
            wh.WaitOne(); // blocks here until `Set()` is called on the AutoResetEvent

            Console.WriteLine(listDog[0].name);
        }
    }

    public class CustomParametersWithWaitHandle
    {
        public AutoResetEvent WaitHandle { get; set; }
        public string Parameter1 { get; set; }
        public int Parameter2 { get; set; }

        public CustomParametersWithWaitHandle(AutoResetEvent h, string parameter1, int parameter2)
        {
            WaitHandle = h;
            Parameter1 = parameter1;
            Parameter2 = parameter2;
        }

答案 1 :(得分:0)

我非常确定您应该使用TimerCallback初始化new TimerCallback(callbackFunct)而不是仅使用函数的名称。这应该是你的名单没有被Bobs填充的原因(我似乎无法理解它甚至可以编译但是...)。像:

Timer addbobs = new Timer(new TimerCallback(callbackFunct), null, 0, 10000);

您的功能应如下所示:

 public void callbackFunct(object state){
      //...
      listDog.Add(new Dog("Bob"));
      //...
 }

有可能在没有新实例的情况下初始化它,但我不太确定...... P.S。:我怀疑这不是您正在使用的代码,因为它甚至无法编译。注意更新它......