C# 如果窗体未处于活动状态,如何调用?

C# 如果窗体未处于活动状态,如何调用?,c#,winforms,C#,Winforms,直到现在,我使用这个方法调用: public string AddText { set { if (listView1.InvokeRequired) { this.Invoke((MethodInvoker)delegate { Textbox.text += value + "\n";

直到现在,我使用这个方法调用:

    public string AddText
    {
        set
        {
            if (listView1.InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate
                {
                    Textbox.text += value + "\n";
                });
            }
            else
            {
                Textbox.text += value + "\n";
            }
        }
    }
问题是:

    var form = Form.ActiveForm as Form1;
    if (form != null)
        form.AddText = "Test";
我正在写一个分析数据包的分析器。我不能一直把表单放在焦点上,因为我必须对应用程序执行操作。我写这个分析器是为了得到一个数据包,这样我就可以分析它了

如果触摸要分析的应用程序,则Form.ActiveForm返回null


是否有一种方法可以调用并设置文本框来添加文本,即使表单不是在所有内容之上?

您可能会使用工作单元模式来处理表单的OnActivation事件

在AddText方法中放入“if active form”复选框。 如果表单未处于活动状态,请将文本放入列表中,以便以后使用

然后,处理表单的OnActivation事件,如果列表中有值,则通过AddText将其推回。然后,当表单被激活时(当表单获得焦点时发生这种情况),文本将被填充


即使OnActivation部分不起作用,这个常规模式也应该起作用。

您可以使用一个工作单元模式来处理表单的OnActivation事件

在AddText方法中放入“if active form”复选框。 如果表单未处于活动状态,请将文本放入列表中,以便以后使用

然后,处理表单的OnActivation事件,如果列表中有值,则通过AddText将其推回。然后,当表单被激活时(当表单获得焦点时发生这种情况),文本将被填充


即使OnActivation部分不起作用,这种通用模式也应该起作用。

我认为问题的根源在于数据包分析器和主窗体之间的紧密耦合。数据包分析器不必知道任何关于活动表单的信息,甚至不必知道存在任何表单。它使事情很难维护,因为它只在非常特定的情况下工作,而这种情况在某些时候已经不真实了

您可以扭转这个问题,并从分析数据包的类中引发一个事件。这为您提供了更好的封装,因为现在包分析器不需要了解应用程序的其余部分。您可以创建自己的事件参数,也可以重用类似System.Diagnostics.DataReceivedEventArgs这样的参数。然后,您的表单可以接收DataReceived事件,并调用自己的AddText将其调用回主线程,无论表单是否可见,它都会工作


至少这会起作用,但它是一个阻塞调用,因此包分析器线程将停止,直到窗体完全处理事件,并且返回到主线程的封送回调。如果paket率不是很高,那也没关系,但是通常你不想停止一个通信线程来等待主线程更新一个文本框。另一种方法是在数据包分析器中使用StringBuilder记录文本,并通过线程安全的公共属性公开它(累积的文本,而不是StringBuilder)。或者,如果需要分离invidual消息,则可以将它们添加到列表中,并让线程安全属性返回一个累积消息数组。然后,您的表单可以使用计时器以适合您的应用程序的任何速率轮询分析器以获取新记录的数据,并且只能在表单可见时进行轮询。它的更新速度不会很快,但对analyzer线程的影响几乎为零,如果它在更新之间整合StringBuilder或列表中的许多消息,而不是将每个数据包连接到Text属性,那么它的总体运行速度应该会更快。

我认为问题的根源在于紧密耦合在数据包分析器和主窗体之间。数据包分析器不必知道任何关于活动表单的信息,甚至不必知道存在任何表单。它使事情很难维护,因为它只在非常特定的情况下工作,而这种情况在某些时候已经不真实了

您可以扭转这个问题,并从分析数据包的类中引发一个事件。这为您提供了更好的封装,因为现在包分析器不需要了解应用程序的其余部分。您可以创建自己的事件参数,也可以重用类似System.Diagnostics.DataReceivedEventArgs这样的参数。然后,您的表单可以接收DataReceived事件,并调用自己的AddText将其调用回主线程,无论表单是否可见,它都会工作


至少这会起作用,但它是一个阻塞调用,因此包分析器线程将停止,直到窗体完全处理事件,并且返回到主线程的封送回调。如果paket率不是很高,那也没关系,但是通常你不想停止一个通信线程来等待主线程更新一个文本框。另一种方法是在数据包分析器中使用StringBuilder记录文本,并通过线程安全的公共属性公开它(累积的文本,而不是StringBuilder)。或者,如果需要分离invidual消息,则可以将它们添加到列表中,并让线程安全属性返回一个累积消息数组。然后,您的表单可以使用计时器以适合您的应用程序的任何速率轮询分析器以获取新记录的数据,并且只能在表单可见时进行轮询。它的更新速度不会很快,但对analyzer线程的影响几乎为零,如果它在更新之间合并StringBuilder或列表中的许多消息,而不是将每个数据包连接到Text属性,那么它的总体运行速度应该会更快。

如果您无法调用问题,那么您的答案是正确的将使用同步上下文,它在应用程序上始终可用。运行线程。以下各点也是如此:

在表单OnLoad中保存SynchronizationContext.Current到static字段的任意位置。 之后,您可以轻松地使用Post或Send方法进行同步或同步