我一直在试图了解更多关于异步任务和线程,但赚不到一吨的进展的。
我试图加载“发动机”型线,将在启动时在后台运行,并能够访问UI线程更新变量,不挂UI线程。
在下面的代码,发动机被调用,并且一个定单对象被创建,其保持(莱特币/ USD)称为最后的电流值,也保持其它几个值,这将是有用的。 此代码成功地分配电流值label1.text。 我不一定需要代码,但我会采取什么方法来创建每秒后台股票对象,并更新与每个新的股票对象值的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;
}
编辑:如果我这样做,LABEL1引发InvalidOperationException由于跨线程操作的企图(label1的在UI线程)。
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<Ticker> GetTickerAsync(BtcePair pair)
{
return Task.Run(() => BtceApi.GetTicker(pair));
}
// etc
}
然后你可以使用一个计时器,触发每秒一次,这将相应地开始了新的任务和更新用户界面:
// 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;
}
请注意,这并不意味着屏幕每秒更新一次......会有新的任务每秒启动一次,只要每个任务完成后,用户界面将被更新。
的使用await
从异步方法在UI线程上开始- -在这里意味着你不必担心使用的用户界面; 整个异步方法将执行在UI线程上,即使取本身发生在不同的线程。
您可以尝试ContinueWith在任务结束时更新标签。 如果你想更新事件前的任务结束,然后提高它由UI线程上注册的事件。 然后,事件可以更新标签。
我想这是Windows窗体。 你可以做“老派风格”,并设置UI线程上的标签文本,你可以通过委托给做的BeginInvoke或调用方法。
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;
}
}