C#股票代码的异步任务

我一直在努力学习有关异步任务和线程的更多信息,但却没有取得很大进展。

我正在尝试加载一个“引擎”类型的线程,该线程将在启动时在后台运行,并且能够访问UI线程以更新变量,而无需挂起UI线程。

在下面的代码中,调用Engine,并创建一个Ticker对象,它保存名为Last的(Litecoin / USD)的当前值,还包含其他几个有用的值。 此代码成功将当前值分配给label1.text。 我不一定需要代码,但我会采用什么方法在后台每秒创建一个ticker对象,并使用每个新的Ticker对象值更新UI线程。

这对背景工作者来说是个好例子吗?

private void Form1_Load(object sender, EventArgs e) { Engine(); } private void Engine() { Ticker ltcusd = BtceApi.GetTicker(BtcePair.LtcUsd); label1.Text = "LTC/USD:" + ltcusd.Last; } 

编辑:如果我执行以下操作,由于跨线程操作尝试(UI线程中的label1),label1抛出InvalidOperationException。

  private void Form1_Load(object sender, EventArgs e) { var t = Task.Factory.StartNew(() => Engine()); t.Start(); } private void Engine() { while (true) { Thread.Sleep(1000); Ticker ltcusd = BtceApi.GetTicker(BtcePair.LtcUsd); label1.Text = "LTC/USD: " + ltcusd.Last; } } 

使用async / await ,获取“异步”类API的最简单方法是调用新任务。 它不是很好,但它会使事情变得更简单。 我可能会创建一个新类,它基本上包含了任务中的所有BtceApi方法:

 public class BtceApiAsync { public Task GetTickerAsync(BtcePair pair) { return Task.Run(() => BtceApi.GetTicker(pair)); } // etc } 

然后你可以使用一个每秒触发一次的计时器,这将启动一个新任务并适当地更新UI:

 // Keep a field of type System.Windows.Forms.Timer timer = new Timer(); timer.Interval = 1000; timer.Tick += DisplayTicker; timer.Start(); ... private async void DisplayTicker(object sender, EventArgs e) { Ticker ticker = await BtceApiAsync.GetTickerAsync(BtcePair.LtcUsd); label1.Text = "LTC/USD: " + ltcusd.Last; } 

请注意,这并不意味着屏幕每秒更新一次……每秒会启动一次新任务 ,每次完成任务后,UI都会更新。

await这里使用await – 来自在UI线程上启动的异步方法 – 意味着您不必担心使用UI; 整个异步方法将在UI线程上执行,即使fetch本身发生在不同的线程中。

您可以尝试使用ContinueWith在任务结束时更新Label。 如果要在任务结束之前更新事件,则引发在UI线程上注册的事件。 然后,事件可以更新标签。

我想这是Windows Forms。 你可以做“旧学校风格”并在UI线程上设置标签文本,你可以通过将委托传递给BeginInvoke或Invoke方法来实现。

  private void Engine() { while (true) { Thread.Sleep(1000); Ticker ltcusd = BtceApi.GetTicker(BtcePair.LtcUsd); UpdateText("LTC/USD: " + ltcusd.Last); } } private void UpdateText(string text) { //Inspect if the method is executing on background thread if (InvokeRequired) { //we are on background thread, use BeginInvoke to pass delegate to the UI thread BeginInvoke(new Action(()=>UpdateText(text))); } else { //we are on UI thread, it's ok to change UI label1.Text = text; } }