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