没有系统地学过C#,所以一直以为C#只是拖拖拽拽,后来发现在程序实现过程中需要注意好多,标题说跨类的做法我不是很赞同,一种好的方法应该是把其他类的方法封装起来然后在winFrm里面调用,而不应该让其他的类涉及到任何和窗体程序相关函数。这个是面向对象程序设计中比较重要的一点。
但是有的时候,如果设计没做好,就可能真的会遇到要有点跨类调用的情况。
就像前几天写了一个基于TCP的C/S自由收发消息的多客户端小程序,如果把socket类处理从winFrm中分开,那么就会发现socket中阻塞的时候,如果要更新UI,就会比较麻烦,因为是跨类。
你不知道什么时候会子线程阻塞,所以我们要做的是对子线程中某时候状态的做事件侦听,然后委托更新UI。
下面我写了三种方法,可能不是最好的,但是相对比较合理的。
有问题欢迎批评指正,共同交流。
首先我定义一个OtherClass类,是一个想要访问UI的非窗体类。 里面有个函数CatchSocket是模拟捕获socket包的,捕获到后在UI上更新。捕获过程是一个线程。
class OtherClass
{
public void CatchSocket()
{
Random rd = new Random();
while(true) {
// 这里可以模拟捕捉客户Socket的,假定Socket内容用捕获的时间代替
int time = rd.Next(1000, 2000);
Thread.Sleep(time);
// 捕获到后我想显示在UI上
// ?????
}
}
}
主窗体的点击后执行button捕获:
public partial class Form1 : Form
{
// 其他想访问UI的类
OtherClass m_obj = new OtherClass();
public Form1()
{
InitializeComponent();
}
private void button_exc_Click(object sender, EventArgs e)
{
BackgroundWorker bgw = new BackgroundWorker();
// 线程执行的内容
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
}
void bgw_DoWork(object sender, DoWorkEventArgs e)
{
m_obj.CatchSocket();
}
// invoke UpdateUI ?????
}
方法 1
主窗体代码:略
class OtherClass
{
public void CatchSocket(Object WinFrm)
{
Random rd = new Random();
while(true) {
// 这里可以模拟捕捉客户Socket的,假定Socket内容用捕获的时间代替
int time = rd.Next(1000, 2000);
Thread.Sleep(time);
// CatchSocket执行时把窗体对象引用传入
// 然后调用一个WinFrm的public函数(用invoke)去更新
// 不推荐:因为WinFram中就有OtherClass的实例对象,不太好。
// 略…………
}
}
}
方法 2