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

发布于 2024-12-11 12:33:16 字数 827 浏览 0 评论 0原文

所以我有一个有趣的问题(无论如何对我来说)。我正在编写一个应用程序,该应用程序运行扫描并将信息从类发布回 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”中的自定义事件?或者,如果有其他方法可以做到这一点,我很乐意看到一些替代方案。

So I have an interesting problem (to me anyway). I am writting an application that runs a scan and posts information from a class back to a Windows Form. Right now I am creating an instance of a form, accessing the ActiveForm, then posting some text to a public function in that form.

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

So right now this works pretty well. The problem is when the user changes focus away from the Windows Form the text stops updating, which is why I have "if (form != null)". I know this is not an ideal way to do what I am trying to do, so my question is how can I change this code to be something like a custom event in "MyWinForm1"? Or, if there is any other way to do this I would love to see some alternatives.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

⒈起吃苦の倖褔 2024-12-18 12:33:16

有几种方法可以实现您想要的目标。

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) 您可以向扫描类添加自定义事件,然后将委托挂钩到 WinForm 中的回调[再次,您的 WinForm 将需要对扫描类的引用]:

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

There are a couple ways of achieving what you want.

1) You can add a reference to the target form as a property of Scan.cs class

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

then you can pass the reference to your scan class into the WinForm1 instance and set the appropriate property [in this case I'm passing the scanner class using the WinForm constructor]:

  public void WinForm1(Scan scanner)
  {
      if (scanner != null) scanner.WinFormReference = this;
  }

2) You can add a custom event to the scan class and then hook the delegate to a callback in your WinForm [again, your WinForm will need to have a reference to your scan class]:

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

Then you hook up the callback in your form's constructor (or elsewhere):

    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;
        });
    }
花落人断肠 2024-12-18 12:33:16

您可以使用 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);
        }
    }

You can have something like following which use 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);
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文