从多线程类到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"的自定义事件?或者,如果有任何其他方法可以做到这一点,我希望看到一些替代方案。

从多线程类到Windows ActiveForm的事件文本回发

有几种方法可以达到你想要的效果。

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);
        }
    }