处理线程内的用户界面(Compact-Framework)

时间:2014-12-12 15:27:38

标签: c# multithreading compact-framework windows-ce

我们要显示"正在加载,请稍候......"应用程序开始在Win CE 5.0驱动的设备上执行其他功能之前的屏幕。该应用程序正在使用.NET Compact Framework 3.5(C#)开发。

问题在于,UI仅在完成当前进程集时更新到其他功能仅与用户交互一起运行的阶段。 C#有一个Form.Shown()事件,它允许应用程序运行其他函数,只有ONCE表单已经显示。但是,Compact-Framework会 NOT 包含。

我接近的解决方案是使用多线程,我将有一个线程显示"正在加载,请等待......"屏幕,另一个将负责其他功能。

线程问题是,在管理UI组件时,如果没有应用正确的技术,则会出错:

    public Form1()
    {
        InitializeComponent();

        ThreadStart tstart = new ThreadStart(showLoad);
        Thread t1 = new Thread(tstart);
        Thread t2 = new Thread(checkConnect); 

        t1.Start();
        t2.Start();
    }

    private void checkConnect()
    {

        conn.portConnect(); //Connects to port Successfully
        if (conn.isConnected == true) //Variable which checks the connectivity status
        {
            panelMENUshow(); 
        }
        else
        {
            panelCONFIGshow();
        }
    }

    private void showLoad()
    {
        if (imgLoading.InvokeRequired)
        {
            imgLoading.Invoke((Action)(() => imgLoading.Show())); //Image box displaying "Loading, please wait..." shows successfully if I use Control.Invoke
        }

        //If I don't use Control.Invoke I get the following error:
        //"Control.Invoke must be used to interact with controls created on a separate thread."
    }

showLoad()函数上,添加Control.Invoke不是问题。但是,函数panelMENUshow()panelCONFIGshow()包含许多管理UI组件的代码,在引用UI组件的每行代码中使用Control.Invoke是不切实际的。

有没有办法:

  1. 停止线程但继续运行涉及UI管理的代码?
  2. 实际管理线程中的UI组件?
  3. PS:该方法基于answer of this post

2 个答案:

答案 0 :(得分:0)

答案 1 :(得分:0)

编写WinForm应用程序时,您希望保持线程的复杂性远离主UI线程。我已经看到过多的应用程序,其中的线程代码编织进出,将逻辑绑定到一个结。

相反,将需要任何类型的线程的任何东西建模为一个组件,虽然它可以在内部使用线程,但它向外界提供了一个友好的,基于均匀的模型。这些组件不应与您的UI直接交互。

考虑到这一点,你的代码会看起来更像这样(只是一个例子,没有语法检查,可能有很多拼写错误等,但它会给你一个想法):

public class CommunicationObject
{
    // you will probably have several EventArgs to define to pass extra info
    public event EventHandler<EventArgs> Connected;

    // you need this instance to dispatch events to the UI thread
    private Control _invoker;

    public CommunicationObject(Control invoker)
    {
       _invoker = invoker;

       // start a thread here, or better yet, add an Enabled property or
       //   Start method to kick it off
    }

    // from the thread that is doing the real work, call this when you are connected 
    private void OnConnected()
    {

        _invoker.Invoke(() => 
        { 

            EventHandler<EventArgs> handler = Connected;
            if (handler != null)
            {
                handler(this, EventArgs.Empty); // eventually you might need your own event args
            }

        });

    }
}

public class Form1 : Form
{
    private CommunicationObject _comm;

    public Form1()
    {
        InitializeComponent();

        imgLoading.Show(); // show msg until connected

        _comm = new CommunicationObject(this);

        _comm.Connected += Comm_Connected; // wire up event handler
    }

    private void Comm_Connected(object src, EventArgs e)
    {
        if (imgLoading.Visible)
        {
            imgLoading.Hide(); // hide once connected
        }

        panelMENUshow(); 

    } 
}

请注意,表单根本没有线程。将这种复杂性推向独立的对象。这可能看起来有点多了,但你以后会感谢自己!