0

データサーバーからの時間を更新するスレッドタイマーを持つプログラムがあります。ただし、タイマーが数回実行され、その後呼び出しを停止することに気付きました。スレッド タイマー コードを新しいプログラムにコピーしようとすると、正常に動作するので、タイマー コードがプログラムの残りの部分に干渉しているに違いないことはわかっていますが、どこにあるのかわかりません。誰か助けてください。

プログラムはここにすべてを投稿するにはかなり大きいので、関連するすべての部分をここに投稿しようとしています。

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));
    }

干渉の可能性がある場所を指摘できる人はいますか?

4

2 に答える 2

1

タイマー コールバックで行っていることがすべて UI の更新である場合は、System.Windows.Forms.Timer代わりに使用することをお勧めします。InvokeRequired/を処理する必要はありませんBeginInvoke。そのハンドラーは UI スレッドで実行されるためです。

にローカル変数を使用しているようにも見えますSystem.Thread.Timer。これにより、 の実行後にタイマーがファイナライズされる可能性がありHistoricalDownloadます。おそらく、タイマーの実行を停止するよりもはるかに早いでしょう。( http://msdn.microsoft.com/en-us/library/saba8ksxの最初の注を参照してください) 親クラスのフィールドにその変数を配置する必要があります。実行するタイマー。使っていれば問題ないと思いますSystem.Windows.Forms.Timer。ただし、非同期で使用されるもののためにフィールドを保持することもお勧めします。

于 2012-07-31T19:09:16.997 に答える
0

タイマーの Tick イベントがThreadPool スレッドで発生している可能性があります (フレームワーク タイマーの多くはこれを行いますが、カスタム タイマー ( ZenFire?) を使用しているため、確実に知ることはできません)。

この場合、コードはスレッド セーフではない可能性が高く、タイマーの Tick イベント内で例外が発生している可能性があります。繰り返しますが、実装によっては、例外により、その時点以降にタイマーが正しく機能しなくなる場合があります。

特に注意すべき点は、タイマーの Tick イベントから UI コンポーネントを更新しないControl.InvokeことDispatcher.Invokeです。また、あなたのような単純なものDictionary<T,U>はスレッドセーフではないため、これらのアイテムへのアクセスを同期する必要があります。

于 2012-07-31T19:05:15.703 に答える