我是编程新手,只是想知道我得到的问题的解决方案是否合适。
我想将一个状态(字符串)写入一个创建Socket的类的文本框中,该类侦听要接收的数据(在另一个线程中)。
这就是我所做的:
单击按钮,在Form.cs中创建类:
private void button_Create_Click(object sender, EventArgs e)
{
int port;
Int32.TryParse(textBox_Port.Text, out port);
ServerSocketClass serverSocket = new ServerSocketClass(port, this);
}
ServerSocketClass看起来像:
class ServerSocketClass
{
Socket ServerSocket;
Socket Accepted;
IPEndPoint LocalEndpoint;
int Port = 1337; // just for fun
Messenger MainForm;
public ServerSocketClass(int port, Messenger form)
{
MainForm = form;
if (port != 0)
Port = port;
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
LocalEndpoint = new IPEndPoint(IPAddress.Any, Port);
MainForm.writeToMessages("Binding Endpoint to Socket...");
ServerSocket.Bind(LocalEndpoint);
MainForm.writeToMessages("Starting ServerListener Thread...");
Thread ServerListenThread = new Thread(startListening);
ServerListenThread.Name = "ServerListenerThread";
ServerListenThread.Start();
}
private void startListening()
{
ServerSocket.Listen(5);
MainForm.writeToMessages("Whaiting for incoming connections...");
Accepted = ServerSocket.Accept();
whaitForData();
}
并更新表单类中的GUI我创建了一个委托和一个带有调用的“update”方法:
public delegate void writeMessege(string message);
public writeMessege MessegeDelegate;
public void writeToMesseges(string messege)
{
if (InvokeRequired)
{
this.Invoke(MessegeDelegate, new object[] { messege });
return;
}
textBox_Messeges.AppendText("SYSTEM: " + messege + "\n");
}
它有效,但我想知道这是否是一种“有效”的方式,或者我应该去开发者地狱; - )
提前致谢
洛克
答案 0 :(得分:0)
这是一种非常有效的方法,尽管它是否正确"很大程度上取决于上下文 - 你调用它的频率,你想在其中做什么,以及你需要调用它的代码。有许多不同的方法可以在不调用的情况下完成它,但使用InvokeRequired / Invoke没有任何问题 - 这就是它的用途。您可以使用一个调用自身的更新方法,这几乎与您的代码相同,但稍微不那么详细:
public void WriteMessages(string message)
{
if (InvokeRequired)
{ this.Invoke(new Action<string>(WriteMessages), new object[] { message }); }
else
{ textBox_Messages.AppendText("SYSTEM: " + message + "\n"); }
}
Invoke / InvokeRequired上已有很多帖子。作为起点,检查: Isn't blindly using InvokeRequired just bad practice?
答案 1 :(得分:0)
我有类似的情况,我有一个从其他类调用的类,有许多单独的线程,我不得不从所有其他线程更新一个特定的表单。因此,在表单中使用表单中的处理程序创建委托和事件就是答案。所以我想分享它,因为它似乎更简单(即使不一定是更好的解决方案)。
对我有用的解决方案:
我在类中创建了一个事件,我想在另一个表单上进行更新。 (当然,我首先在类中实例化了表单(称为SubAsstToolTipWindow
)。
然后我使用此事件(ToolTipShow
)在我想要更新标签的表单上创建一个事件处理程序。像魅力一样工作。
我使用this description在执行更新的类中设计我自己的代码:
public static class SubAsstToolTip
{
private static SubAsstToolTipWindow ttip = new SubAsstToolTipWindow();
public delegate void ToolTipShowEventHandler();
public static event ToolTipShowEventHandler ToolTipShow;
public static void Show()
{
// This is a static boolean that I set here but is accessible from the form.
Vars.MyToolTipIsOn = true;
if (ToolTipShow != null)
{
ToolTipShow();
}
}
public static void Hide()
{
// This is a static boolean that I set here but is accessible from the form.
Vars.MyToolTipIsOn = false;
if (ToolTipShow != null)
{
ToolTipShow();
}
}
}
然后我的表单中的代码已更新:
public partial class SubAsstToolTipWindow : Form
{
public SubAsstToolTipWindow()
{
InitializeComponent();
// Right after initializing create the event handler that
// traps the event in the class
SubAsstToolTip.ToolTipShow += SubAsstToolTip_ToolTipShow;
}
private void SubAsstToolTip_ToolTipShow()
{
if (Vars.MyToolTipIsOn) // This boolean is a static one that I set in the other class.
{
// Call other private method on the form or do whatever
ShowToolTip(Vars.MyToolTipText, Vars.MyToolTipX, Vars.MyToolTipY);
}
else
{
HideToolTip();
}
}
答案 2 :(得分:0)
很久以前,但我希望你们都知道我最终解决了这个让我完全满意的事情(用事件解决了 - 当然; - )):
我定义了一个EventArgs来传递我想传递的所有信息:
public class IncomingMessageEventArgs : EventArgs
{
private Message _message;
public Message Message
{
get
{
return _message;
}
}
public IncomingMessageEventArgs(Message message)
{
_message = message;
}
}
在发布信息的类(到WPF - 表单)上定义事件及其处理程序:
public delegate void IncomingMessageEventHandler(object sender, IncomingMessageEventArgs e);
public event IncomingMessageEventHandler IncomingMessageEvent;
protected void OnIncomingMessageEvent(IncomingMessageEventArgs e)
{
if (IncomingMessageEvent != null)
IncomingMessageEvent(this, e);
}
当然,如果需要更新WPF表格(也在&#34;信息发送类&#34;),则提升事件:
OnIncomingMessageEvent(new IncomingMessageEventArgs(message));
在WPF类上你需要监听事件,但首先要定义一个EventHandler,因为你的信息来自一个不同的线程!! : private delegate void writeMessageToChatEventHandler(object sender,IncomingMessageEventArgs e);
现在我们编写我们的方法将处理引发的事件:
// Write to Chat
private void writeMessageToChat(object sender, IncomingMessageEventArgs e)
{
try
{
if (!Dispatcher.CheckAccess())
{
Dispatcher.Invoke(new writeMessageToChatEventHandler(writeMessageToChat), new object[] { sender, e } );
return;
}
textBox_Chat.AppendText(e.Message.getFormatedMessageText() + "\n");
}
catch (Exception ex)
{
writeLogToChat(this, new IncomingLogEventArgs("ERROR: " + ex.Message));
}
}
最后,我们需要订阅事件当然(第一种方法,你可以忽略,它只是为了满足MS Nameing约定:
private void ClientSocket_IncomingMessageEvent(object sender, IncomingMessageEventArgs e)
{
writeMessageToChat(sender, e);
}
ClientSocket.IncomingMessageEvent += ClientSocket_IncomingMessageEvent;
希望我这样做是可以理解的:P 感谢所有人对我的帮助!
再见