如何使用多个线程更新Windows表单文本框值



这个问题与以前的类似问题不同。我还没有从他们那里找到我的问题的答案。我正在运行2个线程。线程#2接收消息,从中解析数据并准备在Windows表单GUI中显示。线程#1运行Windows形式GUI显示并更新其中的文本框值。我已经在两个不同类别的类别中创建了一个事件和事件处理程序,而不是Setoperations类。setoperations是我的表格所在的类。我的代码编译并运行没有错误。我的活动似乎开火了,活动处理程序似乎接收了数据。我的文本框的参数值似乎也被分配了。我的问题是,当事件处理程序结束时,我看不到更新的文本框值。

以下是凝结代码的片段。我希望它可以说明GUI显示的类之间如何传递消息数据。我是新手,所以请原谅我的一些无知。有人建议我忽略了什么吗?事件处理程序是否需要位于Setoperations类或其他地方以更新文本框值?

谢谢您的建议,任何人都可以分享。

static class Program
    {
        // The main entry point for the application.
        [STAThread]
        static void Main()
        {
            Aag_Listen AagListen1 = new Aag_Listen();
            Trace.WriteLine("Application:  Thread #1 and #2: about to start");
            // starts Thread #2 where the Aag (server) listens for the Lru (client) message
            Thread AagListenThread = new Thread(new ThreadStart(AagListen1.ListenForLru));
            AagListenThread.Start();
            while(!AagListenThread.IsAlive)
                ;
            Thread.Sleep(3000);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new SetOperation());    // this runs in Thread #1
        }
    }

    // Class is the beginning of Thread #2:  Aag (server) listens for Lru (client) incoming message
    // Gets the message data; calls to prepare it to be displayed by GUI; It then responds to the Lru
    // 1) listens for the Lru msg, accesses and reads it into an object
    // 2) passes the object with the message string to the AagPrepDisplay class
    public class Aag_Listen
    {
        #region Fields
        private Aag_Listen mAagListen2;
        private string lruString;
        internal Aag_PrepDisplay AagPrepDisplay;    // need external access by Thread #1
        #endregion Fields
        #region Properties
        public Aag_Listen AagListen2
        {
            get { return mAagListen2; }
            set { mAagListen2 = value; }
        }
        public string LruString
        {
            get { return lruString; }
            set { lruString = value; }
        }   
        #endregion Properties
        #region Methods
        // Aag (server) begins to listen for a Lru (client) message
        public void ListenForLru()
        {
            AagShowRequestData();
        }
        // Aag listener reads status of message data sent
        public void AagShowRequestData()
        {
            mAagListen2 = new Aag_Listen();
            this.AagPrepDisplay = new Aag_PrepDisplay();
            // this simulates updating each channel with message data as received from the Lru (client)
            int chan = 1;
            while(true)
            {
                    // display 405.1 and other message values
                    switch(chan)
                    {
                        case 1:
                            mAagListen2.LruString = "<tdrop><path sondeID="11024"chanNum="1"rxFreq="405.1" />" +
                            "<sample frameNum="3440"nsats="4"gdop="25.5"battery="5.58"time="403892.500"" +
                            "posx="-4738495.06"posy="-2993107.15"posz="-3044438.50"gpsWeek="706" /></tdrop>";
                            Trace.WriteLine("mAagListen2.LruString = " + mAagListen2.LruString);
                            chan = 3;
                            break;
                        case 2:
                            mAagListen2.LruString = "<tdrop><path sondeID="11024"chanNum="3"rxFreq="405.1" />" +
                            "<sample frameNum="3440"nsats="4"gdop="25.5"battery="5.58"time="403892.500"" +
                            "posx="-4738495.06"posy="-2993107.15"posz="-3044438.50"gpsWeek="706" /></tdrop>";
                            Trace.WriteLine("mAagListen2.LruString = " + mAagListen2.LruString);
                            chan = 4;
                            break;
                        default:
                            break;
                    }
                }
                AagPrepDisplay.PrepareDisplay(AagListen2);  // prepares data for Windows Form GUI display
            }
        }
        #endregion Methods
    }

        // Class runs in Thread #2:  Aag (server) prepares received Lru (client) message data for Windows Form GUI display 
    // 1) receives from Aag_Listen class message and determines if it's a correct message
    // 2) creates an object and extracts parameter values from message and assigns to object.
    public class Aag_PrepDisplay
    {
        #region Fields
        private string chanNum;
        private string receiveFreq;
        private DateTime date_time;
        private static int first;
        private static int last;
        private Aag_PrepDisplay mAagPrep;
        #endregion Fields
        #region Properties
        public Aag_PrepDisplay AagPrep
        {
            get { return mAagPrep; }
            set { mAagPrep = value; }
        }
        }
        public string ReceiveFreq
        {
            get { return receiveFreq; }
            set { receiveFreq = value; }
        }
        public string ChanNum
        {
            get { return chanNum; }
            set { chanNum = value; }
        }
        #endregion Properties
        #region Methods
        // begins extracting message parameters for Windows Form GUI display
        public void PrepareDisplay(Aag_Listen aagListen2)
        {
            mAagPrep = new Aag_PrepDisplay();
            Aag_DisplayEvent AagDisEvt1 = new Aag_DisplayEvent();
            bool Tdrop = aagListen2.LruString.Contains("tdrop");            // search for correct message
            if(!Tdrop)                              // reject string if not correct
                return;
            else
            {   //search message data string for channel parameters to prepare for Aag display
                // search for channel number from message; extract and save as string
                first = aagListen2.LruString.IndexOf("chanNum="") + "chanNum="".Length;
                last = aagListen2.LruString.IndexOf(""rxFreq");
                String substring = new String('1', 1);
                mAagPrep.ChanNum = aagListen2.LruString.Substring(first, last - first);
                Trace.WriteLine("mAagPrep.ChanNum = " + mAagPrep.ChanNum);
                AagDisEvt1.ChDet += new ChDetHandler(OnChDetDisplay);   // hooks handler to event
                AagDisEvt1.ChDetDisplay(AagPrep);  // passes the object w/message parameters to AagDisplayEvent class to fire the event 
            }
        }
        // event handler called from Aag_DisplayEvent class
        public void OnChDetDisplay(object sender, ChanEventArg e)
        {
            SetOperation SetOp1 = new SetOperation();
            SetOp1.updateAll(AagPrep);
        }   //******* PROBLEM HERE:  WHY doesn't Windows Form actual frequency textbox update when this event closes?  PROBLEM HERE:*********
        #endregion Methods
    }

    // class handles the event argument that is the AagPrep class object containing all message parameters
    public class ChanEventArg : EventArgs
    {
        public object Name;
        public ChanEventArg(object name)
        {
            Name = name;
        }
    }
    public delegate void ChDetHandler(object sender, ChanEventArg e);   // declare delegate 
    // class is acting server that handles event notification
    public class Aag_DisplayEvent
    {
        public event ChDetHandler ChDet;    // delegate object reference declared
        // helper method to help call delegate object for event
        protected void OnChDet(ChanEventArg e)
        {
            if(ChDet != null)
            {
                ChDet(this, e);     // calls event
            }
        }
        // fires event by calling helper method 
        public void ChDetDisplay(object name)
        {
            OnChDet(new ChanEventArg(name));
        }
    }
    // this class is the Windows Form running in Thread #1.  It displays and updates all Window Form textboxes. 
    public partial class SetOperation : Form
    {
        public SetOperation()
        {
            Trace.WriteLine("Thread #1:  Set Operations Launched");
            InitializeComponent();
        }
        // updates the Aag (server) actual received frequency GUI display as received by the Lru (client) channel message
        public void updateActFreq(Aag_PrepDisplay aagPrep)
        {
            Trace.WriteLine("Update Actual Frequency Selected");    
            switch(aagPrep.ChanNum)
            {
                case "1":
                    Trace.WriteLine("Update ActFreqChan1 Selected");
                    ActFreqChan1.Text = aagPrep.ReceiveFreq;                // Lru (client) actual received frequency 
                    break;
                case "2":
                    Trace.WriteLine("Update ActFreqChan2 Selected");
                    ActFreqChan2.Text = aagPrep.ReceiveFreq;
                    break;
                case "3":
                    Trace.WriteLine("Update ActFreqChan3 Selected");
                    ActFreqChan3.Text = aagPrep.ReceiveFreq;            // PROBLEM: Why is this not updated in Windows Form textbox?
                    Trace.WriteLine("aagPrep.ReceiveFreq = " + aagPrep.ReceiveFreq);
                    Trace.WriteLine("ActFreqChan3.Text = " + ActFreqChan3.Text);  // NOTE: this does reflect the updated actual frequency.
                    break;
                default:
                    break;
            }           
        }
        // called from the Aag_DisplayEvent class event handler to update the actual frequency in Windows Form textboxes
        public void updateAll(Aag_PrepDisplay aagPrep)
        {
            Trace.WriteLine("Update All Selected"); 
            updateActFreq(aagPrep);
        }
    }

您的问题与此主题的所有其他问题完全一样。有三种方法可以将方法调用到UI线程,虽然我没有详细阅读您的代码,但我不会看看您在哪里使用的代码。这就是问题。一种方法适用于Winforms表单或控件中的代码,一种方法适用于WPF Windows和控件,而第三个则适用于无法直接访问控件的Winforms或WPF应用中的代码。我在这里展示了这三个。在您的情况下实施最合适的。如果您希望表单或控件进行编组,请使用issynchronizeInvoke,如果您希望类在UI线程上提出事件,即使它不是UI元素本身,请使用Synchronization -context。

相关内容

  • 没有找到相关文章

最新更新