表单应用中的无意多线程

时间:2016-07-26 22:37:35

标签: c# asp.net .net multithreading forms

我最近通过Visual Studio中的Windows窗体应用程序模板创建了一个窗体应用程序。我认为该程序是使用多个线程自动创建的,将UI放在一个线程上以及另一个线程上的其他任何线程上。我没有在应用程序中放置任何代码来使用多线程。

无论我遇到并修复了here所描述的错误。抛出错误是因为我从下面的代码块中访问了一个UI对象。问题在于代码是从与UI的线程不同的线程运行的。

我想知道的是实际使用多线程的程序?如果是这样,我该如何防止这种情况发生。如果没有,这里发生了什么?

作为参考,我遇到此问题的代码与我初始化表单的同一个类。我遇到问题的那一行是在CheckUp函数的最后一行(已被更改为允许不同的线程访问)。 注意:代码的结构是移动到控制台应用程序,因此计时器方法和其他一些东西不那么犹太

public partial class Form : System.Windows.Forms.Form
{
    public Form() {
        InitializeComponent();
        System.Timers.Timer actionTimer = new System.Timers.Timer(1000);
        actionTimer.Elapsed += actionTimerTick;
        actionTimer.AutoReset = true;
        actionTimer.Enabled = true;

    }


    private void actionTimerTick(object sender, EventArgs e) {
        CheckUp();
    }


    public void CheckUp() {
        bool onlineStatus = GetOnlineStatus();
        string status = (onlineStatus) ? "Online" : "Offline";

        statusOutputLabel.Invoke((Action)(() => statusOutputLabel.Text = status ));
    }

    private static bool GetOnlineStatus() {
        /*unrelated*/
    }
}

2 个答案:

答案 0 :(得分:2)

  

我想知道的是如何操作程序在一个线程上运行所有内容,以便我不必担心添加额外的代码来操作UI对象,

易。只是不要在Windows窗体应用程序中添加任何显式的创建线程代码。

  

我最近通过Visual Studio中的Windows窗体应用程序模板创建了一个窗体应用程序。该程序是使用多个线程自动创建的,将UI放在一个线程上以及另一个线程上的其他任何线程(我认为)。

Windows窗体应用程序模板创建的应用程序默认情况下是固有的单线程,因此不确定为什么您认为自己有其他线程。

如果您确实创建了与other post相关的其他工作线程,那么您应该使用Control.BeginInvoke而不是Control.Invoke,因为后者可能导致潜在的线程死锁。

其他

像WinForms这样的GUI工具包可能总是单线程的。关于为什么要查看this article,请快速阅读。

KGH:

  

输入事件处理的问题是它往往在相反的方向运行到大多数GUI活动。通常,GUI操作从一堆库抽象的顶部开始并“向下”。我在我的应用程序中运行一个由一些GUI对象表示的抽象概念,所以我从我的应用程序开始,调用高级GUI抽象,调用较低级别的GUI抽象,调用丑陋的内容。工具包,然后进入操作系统。相比之下,输入事件从OS层开始,逐步向上调度抽象层,直到它们到达我的应用程序代码。   现在,由于我们使用抽象,我们自然会在每个抽象中单独进行锁定。不幸的是,我们有经典的锁定订单噩梦:我们有两种不同类型的活动,希望获得相反订单的锁定。 所以僵局几乎是不可避免的Golly, tell me more...

这就是为什么像Java AWT一样,WinForms也是单线程的。

另见

答案 1 :(得分:2)

您正在使用System.Timer。 https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx

对于winforms应用程序,最好使用winforms ...

https://msdn.microsoft.com/en-us/library/system.windows.forms.timer(v=vs.110).aspx

它旨在支持单线程UI。 : -

  

Timer用于以用户定义的间隔引发事件。此Windows计时器专为使用UI线程执行处理的单线程环境而设计。它要求用户代码具有可用的UI消息泵,并始终在同一个线程中运行,或者将调用编组到另一个线程上。