如何阻止从另一个线程的UI线程或强制的形式向UI线程中运行

如何阻止从另一个线程的UI线程或强制的形式向UI线程中运行

本文介绍了如何阻止从另一个线程的UI线程或强制的形式向UI线程中运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序的要求是,如果它失去的数据库连接,那么它必须弹出一个大模式无连接,请稍后再试对话框阻止所有用户交互,直至该连接已恢复了。

A requirement for my application is if it looses database connectivity then it must pop up a big modal "No Connection. Try again later" dialog blocking all user interaction until such time that connectivity is regained.

我实现这个由在启动设备监视器类的一个实例的应用程序的启动。此类创建一个System.Threading.Timer,每一个周期(通常为1秒),与它一起试图从数据库中提取数据的一些其他的东西。如果平局和失败的原因被确定为由于缺乏连通性,异常被弹出上述对话框处理。同样地,如果数据取成功并且对话是目前最多母鸡它被强制关闭。

I achieve this by at the start of the application starting an instance of a DeviceMonitor class. This class creates a System.Threading.Timer and every Tick (usually 1 second) along with a few other things it tries to draw data from the database. If the draw fails and the cause is determined to be due to a lack of connectivity, the exception is handled by popping up the aforementioned dialog. Likewise, if the data fetch succeeds and the dialog is currently up hen it is forced closed.

的问题是,尽管这一切工作正常,则ConnectionLost对话框不从与UI相互作用阻止的用户。这是有道理的,因为Timer.Elapsed事件在其自己的线程和noConnectionDialog.ShowDialog()从回调阻塞线程它是但不是在被称作提出的UI线程。

The problem is that although this all works fine, the ConnectionLost dialog does not block the user from interacting with the UI. This makes sense, since the Timer.Elapsed event is raised within its own thread and noConnectionDialog.ShowDialog() is called from within the callback it blocks the thread it is on but not the UI Thread.

据我了解,我需要或者强制noConnectionDialog.ShowDialog()到UI线程中运行或阻止用户界面线程,直到noConnectionDialog.Hide()被调用,但我不知道该怎么办任。

To my understanding I need to either force the noConnectionDialog.ShowDialog() to run within the UI thread or to block the UI thread until noConnectionDialog.Hide() is called but I don't know how to do either.

也许还有一些其他的补救措施或者我失去了一些东西。任何的建议是AP preciated。

Perhaps there is some other remedy or I am missing something here. Any advice is appreciated.

编辑:更多信息 - 这是一个程式化的对话,而不仅仅是一个消息。当我的应用程序开始于温莎城堡它正在创建并注入其中被传来传去一个DialogFactory类。因此,对话是访问

Further information - this is a stylized dialog, not just a messagebox. It is being created when my application starts by Castle Windsor and injected into a DialogFactory class which gets passed around. The dialog is therefore accessed by

var d = _dialogFactory.GetNoConnectionDialog();
d.ShowDialog();

我已经尝试了把这个code经过计时器外回调 - 被点击时在UI界面的一个按钮 - 然后,它会阻止用户界面从那里就好了,所以这是不是那里的形式的问题被创建。

I have experimented with putting this code outside of the timer elapsed callback - when a button on UI interface is clicked for example - and it blocks the UI just fine from there so this is not a matter of where the form is created.

推荐答案

我是pretty的知道马克建议应该工作。这就是我写使用的MessageBox 你的对话,而不是:

I'm pretty sure what Marc suggested should work. This is how I would write it to use your dialog instead of MessageBox:

someControl.Invoke((Action)delegate {
    var d = _dialogFactory.GetNoConnectionDialog();
    d.ShowDialog();
}, null);

如果真的不工作我已经使用Timer控件( System.Windows.Forms.Timer )对我的表单和队列在过去的成功与蜱的功能,看起来像这样操作的:

If that really isn't working I've had success in the past using a Timer control (System.Windows.Forms.Timer) on my form and a queue of Actions with an Tick function that looks like this:

void timer_Tick(object sender, System.EventArgs e)
{
    lock(queue)
    {
        while(queue.Count > 0)
        {
            Action a = queue.Dequeue();
            a();
        }
    }
}

当你的设备监视器类需要显示的用户界面,将做到这一点:

And when your DeviceMonitor class needs to show the UI it would do this:

lock(queue)
{
    queue.Enqueue((Action)delegate
    {
        var d = _dialogFactory.GetNoConnectionDialog();
        d.ShowDialog();
    });
}

话虽这么说,我真的想重申,我认为马克的方法应正常工作,我只会用我的定时器+队列的方法,如果你是绝对肯定的是, Control.Invoke 不会为你工作。

这篇关于如何阻止从另一个线程的UI线程或强制的形式向UI线程中运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 08:01