简体   繁体   English

穿线计时器不起作用,为什么?

[英]threading timer not working, why?

i have a program which i have a threading timer to update the time coming from the data server. 我有一个程序,我有一个线程计时器来更新来自数据服务器的时间。 However, i notice the timer run a few times and stop calling afterwards. 但是,我注意到计时器运行了几次,然后停止调用。 i try and copy the threading timer code onto a new program and it runs fine, so i know somehow the timer code must have interfere with the rest of the program, but i dont know where, can anyone help me out please? 我尝试将线程计时器代码复制到新程序上,并且运行良好,所以我知道计时器代码一定会干扰程序的其余部分,但我不知道在哪里,有人可以帮我吗?

the program is quite big to post everything here, i try to post all the relevant parts here. 该程序很大,可以在此处发布所有内容,我尝试在此处发布所有相关部分。

public partial class HistoricalDownload : Form
{
    static int column = 2;
    static int row = 100;

    string timeFmt = "yyyy/MM/dd HH:mm:ss.fff";

    ZenFire.Connection zf;
    ZenFire.Connection.TickEventHandler tick;
    ZenFire.IProduct product = null;

    System.Windows.Forms.TextBox[,] textbox = new System.Windows.Forms.TextBox[column, row];
    DisplayTimer displayTimer = new DisplayTimer();
    memoryStreamClass msc = new memoryStreamClass();
    Dictionary<string, int> dictionarySymbol = new Dictionary<String, int>();
    delegate void StringParameterDelegate(int j, string value);

    public HistoricalDownload(ZenFire.Connection z)
    {
        InitializeComponent();

        int month = 0;
        int year = 0;

        string symbol;
        string exchange;
        string finalSymbol;

        string[] lineSplit;

        zf = z;
        tick = new ZenFire.Connection.TickEventHandler(zf_TickEvent);
        zf.TickEvent += tick;

                //set the array for name and update time 

        for (int k = 0; k < column; k++)
        {
            for (int j = 0; j < row; j++)
            {
                textbox[k, j] = new System.Windows.Forms.TextBox();
                textbox[k, j].Size = new Size(140, 18);
                textbox[k, j].Name = "textbox_" + k + "_" + j;

                if (j >= 50)
                {
                    textbox[k, j].Location = new System.Drawing.Point((k * 140) + 400, ((j - 50) * 18) + 30);
                }
                else
                {
                    textbox[k, j].Location = new System.Drawing.Point((k * 140) + 20, (j * 18) + 30);
                }

                textbox[k, j].Visible = true;
                Controls.Add(textbox[k, j]);
            }
        }

                //load the config file and subscribe the symbol

                    ....

                ///////////////////////////////////////

        System.Threading.TimerCallback displayCallback = new System.Threading.TimerCallback(timeDisplay);
        System.Threading.Timer displayTimerThread = new System.Threading.Timer(displayCallback, displayTimer, 0, 1000);
    }

    public void timeDisplay(object timerObject)
    {
        DisplayTimer t = (DisplayTimer)timerObject;


        for (int j = 0; j < t.row; j++)
        {
            string value = t.outputTime[j].ToString(timeFmt);

            if (value != "0001/01/01 00:00:00.000")
            {
                writeToTextBox(j, value);
            }
        }
    }

    public void writeToTextBox(int j, string value)
    {
        if (InvokeRequired)
        {
            BeginInvoke(new StringParameterDelegate(writeToTextBox), new object[] { j, value });
            return;
        }
        //// Must be on the UI thread if we've got this far
        textbox[1, j].Text = value;
    } 

    void zf_TickEvent(object sender, ZenFire.TickEventArgs e)
    {
        string product = e.Product.ToString();
        int c = dictionarySymbol[product];

        displayTimer.outputTime[c] = e.TimeStamp;

        msc.fillBuffer(string.Format("{0},{1},{2},{3},{4}\r\n",
                        e.TimeStamp.ToString(timeFmt),
                        product,
                        Enum.GetName(typeof(ZenFire.TickType), e.Type),
                        e.Price,
                        e.Volume));
    }

can anyone points out where the interference might be? 谁能指出干扰可能在哪里?

If all your're doing in your timer callback is updating the UI, I'd suggest using System.Windows.Forms.Timer instead. 如果您在计时器回调中所做的所有工作都是在更新UI,建议您改用System.Windows.Forms.Timer You don't have to deal with InvokeRequired / BeginInvoke because that handler runs on the UI thread. 您不必处理InvokeRequired / BeginInvoke因为该处理程序在UI线程上运行。

It also appears that you using a local variable for your System.Thread.Timer . 似乎还为System.Thread.Timer使用了局部变量。 That could cause the timer to be finalized after the execution of HistoricalDownload . 这可能导致计时器在执行HistoricalDownload之后完成。 Which is probably much sooner than you want the timer to stop running. 这可能比您希望计时器停止运行要早得多。 (see first Note at http://msdn.microsoft.com/en-us/library/saba8ksx ) You should put that variable in a field of the parent class--or whatever class will stay "alive" as long as you want the timer to run. (请参见http://msdn.microsoft.com/zh-cn/library/saba8ksx上的第一个注释),您应该将该变量放在父类的字段中,否则任何类都将保持“活动”状态,只要您愿意计时器运行。 I don't think that would be an issue if you used System.Windows.Forms.Timer . 我认为如果使用System.Windows.Forms.Timer不会有问题。 But, it's a good idea too keep a field around for something that get's used asynchronously. 但是,这也是一个好主意,可以为异步使用的内容保留一个字段。

The Tick event for the timer may be occurring on a ThreadPool thread (many of the framework timers do this, but since you're using a custom timer ( ZenFire ?), it's impossible to know for sure). 计时器的Tick事件可能在ThreadPool线程上发生(许多框架计时器都在执行此操作,但是由于您使用的是自定义计时器( ZenFire ?),因此无法确定)。

If this is the case, your code is likely not thread safe, and you may be getting an exception within your timer's Tick event. 在这种情况下,您的代码可能不是线程安全的,并且您的计时器的Tick事件中可能会遇到异常。 Again, depending on the implementation, the exception may be preventing the timer from functioning correctly after that point. 同样,根据实现方式,异常可能会阻止计时器在此之后正常运行。

The particular things to watch for are to not update any UI components from the timer's Tick event - but install, marshal the calls back to the UI thread with Control.Invoke (or Dispatcher.Invoke if you're using WPF). 要注意的特定事情是不更新计时器的Tick事件中的任何UI组件-而是使用Control.Invoke (如果使用的是WPF,则使用Dispatcher.Invoke )安装,封送回UI线程的调用。 Also, simple things like using your Dictionary<T,U> are not thread safe, so you should synchronize access to these items. 另外,使用Dictionary<T,U>类的简单操作也不是线程安全的,因此您应该同步对这些项目的访问。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM