C#多线程以特定间隔调用单个方法

时间:2011-04-04 16:22:03

标签: c# multithreading timer stock

我会尽量使问题变得简单,以便很容易了解情景。我正在尝试为学校项目建立一个与股票相关的应用程序,该应用程序从网络中获取特定股票的数据。因此,用户在文本框中输入库存名称,单击该按钮后,库存的名称将传递给该特定库存的下载数据的方法。现在我想要为同一股票每秒调用该方法,以便用户可以获得最新的更新。直到现在没问题。但是当用户想要监控多个股票时,我需要深入了解线程。至于每个股票,将有一个线程将每秒调用更新股票方法。因此,例如,有5个股票,因此应该有5个线程同时调用该方法每秒更新结果。我希望我能清楚地理解这个问题。

为了实现这一点,我在按钮点击事件中使用System.Threading.Timer,它正在调用股票更新的方法。但问题是,当我输入第一个股票时,方法只被调用2次,第二个股票被调用6次,第三个股票被调用超过12次。这种奇怪行为背后的原因是什么?

任何想法是否有任何其他方法来实现我想要做的事情。 以下是我正在处理的代码。

private void button1_Click(object sender, EventArgs e)
{
    dataGridView1.Rows.Add("","","","","","test", "test");
    int i= dataGridView1.Rows.Count - 1;
    string stock = textBox1.Text + ":"+i;

    System.Threading.Timer tmr = new System.Threading.Timer(Tick,stock,1000,2000);
}

public void Tick(object stock)
{
    lock (locker)
    {
        string maindata = stock.ToString();
        string[] testing = maindata.Split(':');
        byte[] data = null;
        Uri uri = new Uri("some url where i am getting data from");
        WebClient wc = new WebClient();

        wc.DownloadDataCompleted += delegate(object sender, DownloadDataCompletedEventArgs e)
        {
            data = e.Result;
        };
        wc.DownloadDataAsync(uri);
        while (wc.IsBusy)
        {
            Thread.Sleep(100);
        }
        string strData = Encoding.ASCII.GetString(data);
        string[] s = strData.Split('{');
        string data1 = s[4];
        string[] data2 = data1.Split('}');
        string final = "[{" + data2[0] + "}]";

        Form1 obj = new Form1();
        List<Form1> jarray = JsonConvert.DeserializeObject<List<Form1>>(final);

        dataGridView1.Rows[System.Convert.ToInt32(testing[1]) - 1].Cells[0].Value = jarray[0].Symbol;
        dataGridView1.Rows[System.Convert.ToInt32(testing[1]) - 1].Cells[1].Value = jarray[0].Ask;
        dataGridView1.Rows[System.Convert.ToInt32(testing[1]) - 1].Cells[2].Value = jarray[0].Volume;
        dataGridView1.Rows[System.Convert.ToInt32(testing[1]) - 1].Cells[3].Value = jarray[0].Bid;
    }      
}

4 个答案:

答案 0 :(得分:1)

每次点击都会产生新的Timer。这意味着随后的每次点击,更多的计时器都会响应,所以你开始两次,4次,......的事件。

将此行移出Click并将其放入表单的初始化中:

System.Threading.Timer tmr = new System.Threading.Timer(Tick,stock,1000,2000);

这并不意味着我完全赞同你的方法,因为那与你提出的问题毫无关系。

答案 1 :(得分:1)

我建议你看看Asynchronous Programming Using Delegates。在每个tick(仅使用1个计时器)上,您应该异步启动一个委托,以获取用户请求的每个股票的值。

答案 2 :(得分:0)

@Prashant - 显然你的方法不正确。你真正想要发生的是拥有多个线程,这些线程将以不同的间隔打勾。正如Aliostad暗示你的做法不正确。

  

System.Threading.Timer很简单,   使用回调的轻量级计时器   方法,由线程池提供   线程。不建议使用   用Windows Forms,因为它   用户不会发生回调   接口线程。   System.Windows.Forms.Timer是一个更好的   选择与Windows窗体一起使用。对于   基于服务器的计时器功能,你   可能会考虑使用   System.Timers.Timer,它引发了   事件并具有其他功能。

我要做的是使用互斥方法来确定是否需要新线程。我会传递股票的名称,并在线程本身启动计时器。如果你想要一个功能“暂停”或“停止”一只股票被观看就很容易了。

您使用的当前类是线程的,您的方法本身存在缺陷。

As for each stock there will be a thread will be calling the update stock method every second. So for example there are 5 stocks so there should be 5 threads that are working simultaneously calling the method every second to update the results. I hope i have made the problem clear to understand.
  • 除了这不是你在做什么。你实际上正在做的是每按一次按钮(对于每一只股票)都会启动一个新的计时器线程,这当然不是你真正想做的事情(基于你自己的陈述)。

答案 3 :(得分:0)

“但是当用户想要监控多个股票时,我需要深入了解线程”。不对。现在我不想破坏一个非常好的机会,一头扎进线程,但你不需要在这里。为什么不同时刷新所有股票?

因此,每次计时器滴答时,您都会一次性下载所有股票的价格。如果您可以控制服务器端接口(从中获取数据),请创建一个接受stocktickers集合并返回stockprices集合的方法。如果服务器一次只返回一个,那么你就可以循环使用它。

此外,当您真的希望拥有快速响应的内容时,不要每秒轮询新的价格,而是让服务器通过订阅事件来通知您某些事情发生了变化。一些股票不会移动几分钟,而其他股票移动很快。对于大多数交易目的而言,一整秒是一生。如果您使用的是WPF,请查看DataBinding和INotifyPropertyChanged。这非常适合这类问题。

GJ