这个问题与以前的类似问题不同。我还没有从他们那里找到我的问题的答案。我正在运行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。