C#股票代码的异步任务

时间:2013-05-05 18:42:54

标签: c# timer responsive-design task-parallel-library asynchronous

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

我正在尝试加载一个“Engine”类型的线程,该线程将在启动时在后台运行,并且能够访问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;
        }
    }

3 个答案:

答案 0 :(得分:2)

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

public class BtceApiAsync
{
    public Task<Ticker> 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 - 从UI线程上启动的异步方法 - 意味着您不必担心使用UI;整个异步方法将在UI线程上执行,即使fetch本身发生在不同的线程中。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

   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;            
        }
    }
相关问题