在AsyncCallback中启动时,计时器不工作

时间:2012-10-03 12:01:27

标签: c# visual-studio-2008 asynchronous .net-3.5 timer

我需要每5秒调用一次异步操作,因为操作有时可能会更长,我想出来调用方法,然后在我得到结果后等待5秒并再次调用它。

在大班我有类似的东西:

public partial class Form1 : Form
{
    private Timer loopTimer;
    public Form1()
    {
        InitializeComponent();
        loopTimer = new Timer() { Interval = 10000 /*10 seconds*/};
        loopTimer.Tick += loopTimer_Tick;
        EWS.Instance.DoOperation(Operation_OK, Operation_ERROR);
    }

    private void Operation_OK(int count)
    {
        Console.WriteLine("timer start");
        loopTimer.Start();
        Console.WriteLine("timer enabled: " + loopTimer.Enabled);
        Console.WriteLine("async result : " + count);
    }

    private void Operation_ERROR(string err)
    {
        MessageBox.Show(err);
    }

    private void loopTimer_Tick(object sender, EventArgs e)
    {
        Console.WriteLine("tick");
        loopTimer.Stop();
        EWS.Instance.DoOperation(Operation_OK, Operation_ERROR);
    }
}

我的EWS课程如下所示:

class EWS : SingletonBase<EWS>
{
    private EWS()
    {
    }

    private int LongRunningMethod(Action<string> error)
    {
        Console.WriteLine("5 seconds operation");
        Thread.Sleep(5000);
        int unreadCount = 100;
        return unreadCount;
    }

    public class CommandAndCallback<TSuccess, TError>
    {
        public TSuccess Success { get; set; }
        public TError Error { get; set; }
        public Func<Action<string>, int> Delegate { get; set; }
    }

    public void DoOperation(Action<int> success, Action<string> error)
    {
        Func<Action<string>, int> dlgt = LongRunningMethod;
        CommandAndCallback<Action<int>, Action<string>> config = new CommandAndCallback<Action<int>, Action<string>>() { Success = success, Error = error, Delegate = dlgt };

        dlgt.BeginInvoke(error, MyAsyncCallback, config);
    }

    public void MyAsyncCallback(IAsyncResult ar)
    {
        int s;
        CommandAndCallback<Action<int>, Action<string>> config = (CommandAndCallback<Action<int>, Action<string>>)ar.AsyncState;
        s = config.Delegate.EndInvoke(ar);
        Console.WriteLine(s);
        if (s > -1)
            config.Success(s);
    }
}

我可以调用我的方法异步,处理错误,但我不知道为什么我在5秒后无法再调用它。

致电loopTimer_Tick后,我没有拨打{p> loopTimer.Start(); 我重写了几次,每次都无法让定时器工作。

我需要在循环中调用方法(调用交换服务器),但在调用之间有时间间隔,如果有更好的方法可以这样做,请写:)

1 个答案:

答案 0 :(得分:2)

System.Windows.Forms.Timer类不是线程安全的。这里的具体失败是你在线程池线程上调用它的Start()方法。这会创建一个隐藏窗口,提供Tick事件,但它是在错误的线程上创建的。一个不会引发消息循环,因此Tick事件永远不会被引发。

可能的解决方法是在主线程上调用Start(),例如在DoOperation()方法中。或者使用System.Timers.Timer,但要注意其Elapsed事件处理程序在任意线程池线程上运行,因此您无法直接从它访问UI。您应该对实际取消操作采取一些措施,如果您使用BackgroundWorker或Task类,这种代码往往会变得更简单。