Winform之UI后台线程

多线程,一个古老的话题,今天我来聊下最基本的线程,UI线程和后台线程。

在后台线程中直接操作UI控件会出现异常(线程间操作无效:从不是创建控件“XX”的线程访问它)。怎么解决这个问题那?关键点在代理和InvokeRequired属性,Winform的UI(窗口)代码如下:

using  System;
using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Data;
using  System.Drawing;
using  System.Text;
using  System.Windows.Forms;

using  LandpyLibrary;
using  LandpyCommon;

namespace  LandpyWindowsForm
{
    
public   partial   class  MainForm : Form, IFormWorkThread
    {
        
public  MainForm()
        {
            InitializeComponent();
            cdObj 
=  SetTime;
        }

        
private   delegate   void  ControlDelegate( string  time);
        
private  WorkThread wtObj;
        ControlDelegate cdObj;

        
private   void  SetTime( string  time)
        {
            lblTime.Text 
=  time;
        }

        
public   void  ShowTime( string  time)
        {
            
if  (lblTime.InvokeRequired)
            {
                Invoke(cdObj, time);
            }
            
else
            {
                SetTime(time);
            }
        }

        
private   void  btnStart_Click( object  sender, EventArgs e)
        {
            wtObj 
=   new  WorkThread( this );
            wtObj.StartShowTime();
        }

        
private   void  btnEnd_Click( object  sender, EventArgs e)
        {
            
if  (wtObj  !=   null )
            {
                wtObj.EndShowTime();
            }
        }

        
private   void  MainForm_FormClosing( object  sender, FormClosingEventArgs e)
        {
            
if  (wtObj  !=   null )
            {
                wtObj.EndShowTime();
            }
        }
    }
}

为了能在后台线程中操作UI线程,我们的MainForm继承了公共接口IFormWorkThread,接口定义如下:

using System;
using System.Collections.Generic;
using System.Text;

namespace LandpyCommon
{
    public interface IFormWorkThread
    {
        void ShowTime(string time);
    }
}

该接口放在一个独立的Dll中,UI线程和后台线程也均处于不同的程序集中,它们均引用了该接口的Dll。

后台线程类如下:

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Threading;

using  LandpyCommon;

namespace  LandpyLibrary
{
    
public   class  WorkThread
    {
        
private  IFormWorkThread _formWorkThread;
        
private  Thread thread;

        
public  WorkThread(IFormWorkThread formWorkThread)
        {
            _formWorkThread 
=  formWorkThread;
        }

        
public   void  Deal()
        {
            
while  ( true )
            {
                Thread.Sleep(
1000 );
                _formWorkThread.ShowTime(DateTime.Now.ToString());
            }
        }

        
public   void  StartShowTime()
        {
            thread 
=   new  Thread( new  ThreadStart(Deal));
            thread.Name 
=   " TimeThread " ;
            thread.Start();
        }

        
public   void  EndShowTime()
        {
            thread.Abort();
        }
    }
}

其实报异常是因为多线程操作UI控件是非安全的,MS提供了解决方案,关键代码如下:

        public MainForm()
        {
            InitializeComponent();
            cdObj = SetTime;
        }

        private delegate void ControlDelegate(string time);
        ControlDelegate cdObj;

        private void SetTime(string time)
        {
            lblTime.Text = time;
        }

        public void ShowTime(string time)
        {
            if (lblTime.InvokeRequired)
            {
                Invoke(cdObj, time);
            }
            else
            {
                SetTime(time);
            }
        }

通过代理和InvokeRequired属性解决了这个问题。

 

你可能感兴趣的:(WinForm)