从多线程类到Windows ActiveForm的事件文本回发
本文关键字:事件 文本 ActiveForm 多线程 Windows | 更新日期: 2023-09-27 18:11:53
所以我有一个有趣的问题(至少对我来说)。我正在编写一个应用程序,运行扫描,并从类返回到Windows窗体的信息。现在我正在创建一个表单的实例,访问ActiveForm,然后将一些文本发送到该表单的公共函数。
Scan.cs
// Sets the text of scan history in the ui
private void SetScanHistory(string text)
{
MyWinForm1 form = (MyWinForm1)MyWinForm1.ActiveForm;
if (form != null)
{
form.SetText(text);
}
}
MyWinForm1.cs
// Sets the text of txtScanHistory to the text
public void SetText(string text)
{
this.Invoke((MethodInvoker)delegate
{
// txtScanHistory is a TextBox
txtScanHistory.Text += text + Environment.NewLine;
});
}
所以现在这个工作得很好。问题是当用户改变焦点远离Windows窗体的文本停止更新,这就是为什么我有"if (Form != null)"。我知道这不是一个理想的方式来做我想做的事情,所以我的问题是我怎么能改变这个代码是像"MyWinForm1"的自定义事件?或者,如果有任何其他方法可以做到这一点,我希望看到一些替代方案。
有几种方法可以达到你想要的效果。
1)你可以添加一个引用到目标表单作为Scan.cs类的属性 public MyWinForm1 WinFormReference { get; set; }
// Sets the text of scan history in the ui
private void SetScanHistory(string text)
{
if (this.WinFormReference != null)
{
this.WinFormReference.SetText(text);
}
}
,然后你可以传递到你的扫描类的引用到WinForm1实例,并设置适当的属性[在这种情况下,我通过使用WinForm构造函数传递扫描类]:
public void WinForm1(Scan scanner)
{
if (scanner != null) scanner.WinFormReference = this;
}
2)你可以在scan类中添加一个自定义事件,然后将委托挂钩到WinForm中的回调[同样,你的WinForm需要有一个对scan类的引用]:
public class SetScanHistoryEvents: EventArgs
{
public SetScanHistoryEvents(string text)
{
this.Text = text;
}
public string Text { get; set; }
}
public class Scan
{
public event EventHandler<SetScanHistoryEvents> ScanHistoryEvent;
// Sets the text of scan history in the ui
private void SetScanHistory(string text)
{
if (this.ScanHistoryEvent != null)
{
this.ScanHistoryEvent(this, new SetScanHistoryEvents(text));
}
}
}
然后在表单的构造函数(或其他地方)中连接回调:
public MyWinForm1(Scan scanner)
{
if (scanner != null)
scanner.ScanHistoryEvent += new EventHandler<SetScanHistoryEvents>(scanner_ScanHistoryEvent);
}
private void scanner_ScanHistoryEvent(object sender, SetScanHistoryEvents e)
{
this.Invoke((MethodInvoker)delegate
{
// txtScanHistory is a TextBox
txtScanHistory.Text += text + Environment.NewLine;
});
}
您可以像下面这样使用SynchronizationContext
public partial class Form1 : Form
{
SynchronizationContext context;
public Form1()
{
InitializeComponent();
context = SynchronizationContext.Current;
}
// Sets the text of scan history in the ui
private void SetScanHistory(string text)
{
CallFunc(text);
}
private void CallFunc(string TextValue)
{
context.Post(new SendOrPostCallback(
delegate
{
textBox1.Text += TextValue + Environment.NewLine;
}), TextValue);
}
}