从GUI线程上的委托方法更新值,而无需从GUI调用事件

时间:2015-04-26 22:18:27

标签: c# multithreading user-interface trading

我是使用http://www.ctsfutures.com/wiki/T4%20API%2040.MainPage.ashx

中的模板编写的C#程序示例

以下是一些代码:

声明来自其API的moAccounts

internal AccountList moAccounts;

创建代表

private delegate void OnPositionUpdateDelegate(T4.API.Position poPosition);

在Init()内部注册

moAccounts.PositionUpdate += new T4.API.AccountList.PositionUpdateEventHandler(moAccounts_PositionUpdate);

我相信在进入交易并更新头寸时会调用此方法。位置就像你在100股谷歌等等。所以它只有100个。

 //' Event that is raised when positions for accounts have changed.
    private void moAccounts_PositionUpdate(AccountList.PositionUpdateList poPositions)
    {

        // Display the position details.

        {

            foreach (AccountList.PositionUpdateList.PositionUpdate oUpdate in poPositions)
            {
                // If the position is for the current account
                // then update the value.

                if (object.ReferenceEquals(oUpdate.Account, moAccount))
                {
                    // Invoke the update.
                    // This places process on GUI thread.
                    // Must use a delegate to pass arguments.
                    if (this.InvokeRequired)
                    {
                        this.BeginInvoke(new OnPositionUpdateDelegate(OnPositionUpdate), new object[] { oUpdate.Position });
                    }
                    else
                    {
                        OnPositionUpdate(oUpdate.Position);
                    }

                    break; // TODO: might not be correct. Was : Exit For

                }

            }
        }

    }

然后这被称为

        private void OnPositionUpdate(T4.API.Position poPosition)
    {

        if (object.ReferenceEquals(poPosition.Market, moMarket))
        {

            // Display the position details.
            DisplayPosition(poPosition.Market, 1);
        }

    }

然后调用它来更新保存位置数的TextBox

private void DisplayAccount(Account poAccount)
            {

                if ((moAccount != null))
                {

                    try
                    {
                        // Lock the host while we retrive details.
                        moHost.EnterLock("DisplayAccount");

                        // Display the current account balance.
                        txtCash.Text = String.Format("{0:#,###,##0.00}", moAccount.AvailableCash);

                    }
                    catch (Exception ex)
                    {
                        // Trace the error.
                        Trace.WriteLine("Error: " + ex.ToString());

                    }
                    finally
                    {
                        // Unlock the host object.
                        moHost.ExitLock("DisplayAccount");

                    }

                }

            }


            private void DisplayPosition(Market poMarket, int piID)
            {
                string strNet = "";
                string strBuys = "";
                string strSells = "";

                bool blnLocked = false;

                try
                {

                    if ((poMarket != null) && (moAccount != null))
                    {
                        // Lock the host while we retrive details.
                        moHost.EnterLock("DisplayPositions");

                        // Update the locked flag.
                        blnLocked = true;


                        // Temporary position object used for referencing the account's positions.
                        Position oPosition = default(Position);

                        // Display positions for current account and market1.

                        // Reference the market's positions.
                        oPosition = moAccount.Positions[poMarket.MarketID];

                        Trace.WriteLine("Inside of DisplayPosition: " + oPosition.ToString());

                        if ((oPosition != null))
                        {
                            // Reference the net position.
                            strNet = oPosition.Net.ToString();
                            strBuys = oPosition.Buys.ToString();
                            strSells = oPosition.Sells.ToString();

                            // this part is what I added
                           // this is an int value
                            _positionQuantity = oPosition.Net;

                        }

                        switch (piID)
                        {
                            case 1:
                                // Display the net position.
                                txtNetPosition.Text = strNet;
                                break;
                        }

                    }

                }
                catch (Exception ex)
                {
                    // Trace the error.
                    Trace.WriteLine("Error " + ex.ToString());

                }
                finally
                {
                    // Unlock the host object.
                    if (blnLocked)
                        moHost.ExitLock("DisplayPositions");

                }

            }

我注意到如果我从Trace.WriteLine调用_positionQuantity,它不会更新。但是,当我从MessageBox.Show(_positionQuantitiy)调用它时,它会更新。

我的问题是我必须在没有GUI项目的情况下进行内部计算。如何更新_positionQuantity而无需从GUI事件类型事件中调用它,只需在需要时更新它

感谢 斯潘塞

1 个答案:

答案 0 :(得分:0)

必须在创建它们的同一个线程上对Windows窗体控件进行更新。 (也就是说,它们具有线程关联性。)要在UI线程上执行委托,请调用表单的Invoke方法,如下所示:

myForm.Invoke(() => {
                        doThis(someControl);
                        doThat(anotherControl);
                        doTheOther(anotherControl, 42);
                    });

花括号中的东西称为匿名方法。当然,单线工作也是如此:

myForm.Invoke(() => {someControl.Text = "Threads!";});

如果您想立即更新表单的可视状态,可以使用theForm.Refresh();