using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace treadTest
{
//定义委托
public delegate void ListBoxDelegate();
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//委托处理方法(关联与ListBoxDelegate)
private void ListBox()
{
if (!listBox1.InvokeRequired)//如果在UI主线程操作ListBox,
{
listBox1.Items.Add(++CommonData.num);//则直接进行控件操作,“与UI主线程相关联”
listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
}
else//如果是在另一线程操作ListBox,则启用委托
listBox1.Invoke(new ListBoxDelegate(listShow));
}
//定义对UI主线程控件的操作,“与AddAuto相关联”。
private void listShow()
{
listBox1.Items.Add(CommonData.num);
listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
}
//定义线程函数
private void AddAuto()
{
while (CommonData.Flag == 0)
{
CommonData.num++;
Thread.Sleep(1000);
ListBox();//不能直接控制UI上的控件,所以用该方法选择使用委托
}
}
//在click事件中启动多线程
private void btnStart_Click(object sender, EventArgs e)
{
//线程标志置0,表示开启线程
CommonData.Flag = 0;
//定义 ThreadStart的委托类型的参数,并使该委托指向线程函数
ListBoxDelegate mycn = new ListBoxDelegate(AddAuto);
//实例化线程
Thread insertTxt = new Thread(new ThreadStart(mycn));
//启动线程
insertTxt.Start();
}
private void btnAbort_Click(object sender, EventArgs e)
{
CommonData.Flag = 1;
}
private void btnCtrlMain_Click(object sender, EventArgs e)
{
ListBox();
}
private void btnReset_Click(object sender, EventArgs e)
{
CommonData.num = 0;
}
private void btnClear_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
private void btnQuit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
//全局变量解决方案
public class CommonData
{
private static int _Flag = 0;
private static int _num = 0;
public static int Flag
{
get { return _Flag; }
set { _Flag = value; }
}
public static int num
{
get { return _num; }
set { _num = value; }
}
}
}
总结:
要使用多线程控制UI控件,必须用委托实现。调用控件的Invoke方法(Invoke方法的参数是一个委托类型的参数)。
实现步骤:
1.声明委托。
2.声明委托处理函数(判断是主线程控制UI控件,还是Invoke(多线程)控制UI控件)。
3.声明一个线程实例,将线程函数的委托传入ThreadStart()。
4.开启该线程。
5.定义该线程函数,欲控制UI控件,则调用第2步的委托处理函数,他将自己判断选择用Invoke。
6.定义Invoke需要调用的函数(如本例的listShow函数)
//*********************************************************************************************************************************
在上例中,只是完成了多线程控制主线程控件的功能,如果能手动和自动同时访问全局变量时,就有可能出现线程不同步的问题。以下主要利用lock线程锁来修改解决方案,使线程同步,注意代码带动的地方。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace treadTest
{
//定义委托
public delegate void ListBoxDelegate();
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//委托处理方法(关联与ListBoxDelegate)
private void ListBox()
{
if (!listBox1.InvokeRequired)//如果在UI主线程操作ListBox,
{
listBox1.Items.Add(CommonData.plus());//则直接进行控件操作,“与UI主线程相关联”
listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
}
else//如果是在另一线程操作ListBox,则启用委托
listBox1.Invoke(new ListBoxDelegate(listShow));
}
//定义对UI主线程控件的操作,“与AddAuto相关联”。
private void listShow()
{
listBox1.Items.Add(CommonData.plus());
listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
}
//定义线程函数
private void AddAuto()
{
while (CommonData.Flag == 0)
{
Thread.Sleep(1000);
ListBox();//不能直接控制UI上的控件,所以用该方法选择使用委托
}
}
//在click事件中启动多线程
private void btnStart_Click(object sender, EventArgs e)
{
//线程标志置0,表示开启线程
CommonData.Flag = 0;
//定义 ThreadStart的委托类型的参数,并使该委托指向线程函数
ListBoxDelegate mycn = new ListBoxDelegate(AddAuto);
//实例化线程
Thread insertTxt = new Thread(new ThreadStart(mycn));
//启动线程
insertTxt.Start();
}
private void btnAbort_Click(object sender, EventArgs e)
{
CommonData.Flag = 1;
}
private void btnCtrlMain_Click(object sender, EventArgs e)
{
ListBox();
}
private void btnReset_Click(object sender, EventArgs e)
{
CommonData.num = 0;
}
private void btnClear_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
private void btnQuit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
//全局变量解决方案
public class CommonData
{
private static int _Flag = 0;
private static int _num = 0;
public static int plus()
{
lock (new object())
{
return _num++;
}
}
public static int Flag
{
get { return _Flag; }
set { _Flag = value; }
}
public static int num
{
get { return _num; }
set { _num = value; }
}
}
}
分享到:
相关推荐
c# 控件学习例程 控件的详细使用 包含列表、tabctrl等
多线程就是使程序并发(同时)执行几个操作。本文详细讲解例程
线程间操作无效: 从不是创建控件的线程访问它。当我们执行C#程序出现此错误提示时,可以采用委托的方法来解决,但是有个重要问题需要注意...本例程提供了跨线程安全调用控件的方法。
多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理...这里提供简单的多线程例程便于移植。
c#接口详细介绍及实例c#接口详细介绍及实例c#接口详细介绍及实例c#接口详细介绍及实例
c#多线程典型例程
通过多线程的方式实现了UDP收发数据 可以快速学习UDP通讯原理应进行实际应用
凌华204C运动控制卡C#版开发实例,多个轴的异步操作,相对运动,绝对运动,回零
TreeView控件的Node属性表示TreeView控件的树节点集,树节点集中的每个树节点可以包括本身的树节点集,可以使用Add()、Remove()、RemoveAt()方法添加、删除节点。步骤如下: 1、将TreeView控件添加到窗体中,重命名...
易语言多线程许可证基本例程源码,多线程许可证基本例程,子程序1
QD75运动控制模块例程,带注释.zip三菱PLC编程案例源码资料编程控制器应用通讯通信例子程序实例QD75运动控制模块例程,带注释.zip三菱PLC编程案例源码资料编程控制器应用通讯通信例子程序实例QD75运动控制模块例程,带...
本资源针对雷赛运动控制卡 定长运动、连续运动、插补运动、连续插补运动、PVT运动、手轮运动、回原点运动、IO、AD-DA、低速一维位置比较、低速二维位置比较、高速二维位置比较+高速锁存、DA跟随、刀向跟随、龙门跟随...
运动控制卡的动态链接库调用,主要展示如何编写运动控制卡的运动控制程序
C#从入门到精通光盘例程 自己买的书籍附带的光盘,需要的可以下载学习。
stm32单片机多线程实例
C#打印控件的完整应用实例,ReportViewer控件的应用、报表报表的设计,打印预览、直接打印的设计。报表数据的绑定,报表数据的传输。
易语言多线程的运用例程源码,多线程的运用例程,开始,线程运作,销毁全部线程,线程全部暂停,线程全部恢复,取指定内容,挂起线程,恢复线程,创建线程,销毁线程
易语言多线程传递多参数例程源码,利用api实现~ 解决无法传递多参数的问题
C# winform 控件使用代码,包括checkbox、combobox、linklabel、menustrip、notifyicon等二十多种控件的使用方法
C# ChartPlotter高性能图表控件DynamicDataDisplay库+例程+文档