【问题标题】:making a cross-thread call to hide a form visual c#进行跨线程调用以隐藏表单可视 c#
【发布时间】:2016-08-15 14:26:02
【问题描述】:

更新:解决方案自此出现,现在已被接受。由于这个问题的伪代码很清楚,所以解决方案只用了几秒钟。试图从其他看似“重复”的问题中找出解决方案已经花费了很多时间。从我问这个问题的那一刻起,我在 20 分钟内得到了解决方案。所以它不是重复的,可能是迄今为止最清晰的。

虽然有人就此提出了几个类似的问题,但我仍然无法从他们那里整理出一个工作代码。我的主应用程序不在表单上,​​而是在一个单独的类中,该类是一个插件并由主机应用程序执行。

因此,虽然这似乎是一个重复的问题,但事实并非如此。请继续阅读。

我的主班正在做事。然后我有一个向用户显示信息的表单。当用户离开应用程序(主机应用程序失去焦点)时,我需要隐藏此表单。

我使用的 API 非常有限,因此我可以使用的唯一方法是由主机应用程序触发的事件。

我创建了一个每 100 毫秒触发一次的计时器,并检查用户是否关注应用程序。如果没有,则向表单发送命令以隐藏自身。

这种方法的原因是因为宿主应用程序失去焦点只是我需要隐藏表单的众多场景之一,我需要通过相同的方法来引导所有这些。

在其余类中所有工作(Hide() 方法从应用程序的其余部分调用没有问题。 但是当定时器调用Hide()方法时它不起作用,因为定时器在它触发时在不同的线程上。所以调用就变成了跨线程调用。

非常具体的问题是,我需要一个精确的示例代码,如何使用Invoke 使这个调用从计时器事件处理程序到表单的Hide() 方法线程安全。

谢谢。

这是计时器:

private void Controllel_Opened(object sender, EventArgs e)
{
    myTimer.Elapsed += new System.Timers.ElapsedEventHandler(DisplayTimeEvent);
    myTimer.Interval = 50;
    myTimer.Start();
}

public static System.Timers.Timer myTimer = new System.Timers.Timer();
// This method checks different scenarios when the tool tip should be hidden and calls the hiding method
public static void DisplayTimeEvent(object source, System.Timers.ElapsedEventArgs e)
{
    FormHandler.Hide();
}

然后是“FormHandler”类:

public static class FormHandler
{
    private static Form1 frm1 = new Form1();

    public delegate void Form1HideEventHandler();
    public static event Form1HideEventHandler Form1Hide;

    public static void Hide()
    {
        if (Form1Hide != null)
        {
            Form1Hide();
        }

    }
}

然后是表单的代码:

public partial class Form1 : Form
{   
    public Form1()
    {
        InitializeComponent();
        FormHandler.Form1Hide += FormHandler_Form1Hide;
    }

    private void FormHandler_Form1Hide()
    {
        Hide();
    }
}

如果可能的话,我希望得到一个包含准确代码的解决方案。谢谢。

【问题讨论】:

标签: c# multithreading winforms visual-studio timer


【解决方案1】:
private void FormHandler_Form1Hide()
{
    if (InvokeRequired)
    {
        this.Invoke(new Action(() => { FormHandler_Form1Hide(); }));
    }
    else
    {
        Hide();
    }
}

【讨论】:

  • 太棒了!谢谢你。是的,您对添加else 部分的编辑是完美。当我应用你的样本时,我已经有了这个。
  • 只是为了 DRY,我更喜欢在 InvokeRequired 部分调用 self 而不是重复以下相同的代码...类似于:if(InvokeRequired) { this.Invoke(() => FormHandler_Form1Hide()); return; } 然后以防万一函数变得更长,你不必重复你的代码
【解决方案2】:

您需要改用System.Windows.Forms.Timer。这将调用回调度程序线程。

【讨论】:

  • 这就是问题所在,我需要从表单外部调用表单。原因是宿主应用程序失去焦点只是我需要隐藏表单的众多场景之一,我需要通过相同的确切方法引导所有这些。
  • 是的,但是如果您使用该计时器,它将分派回 UI 线程。方法不重要,重要的是线程。
猜你喜欢
  • 2015-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-06
  • 1970-01-01
  • 2010-11-10
相关资源
最近更新 更多