C#多线程启动后UI界面无响应
usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Da...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WinPCapTest
{
public partial class Form1 : Form
{
static Boolean flag = false;
public Form1()
{
InitializeComponent();
}
private void IDC_NETCARD_Click(object sender, EventArgs e)
{
}
private void IDC_START_Click(object sender, EventArgs e)
{
flag = true;
Thread thread = new Thread(new ThreadStart(Test));
thread.IsBackground = true;
thread.Start(); }
private void IDC_STOP_Click(object sender, EventArgs e)
{
flag = false;
}
delegate void add();
public void Test()
{
this.BeginInvoke(new add(DoWork));
}
//工作者方法
public void DoWork()
{
int i = 0;
while (flag == true)
{
this.IDC_TEXT.AppendText((i++) + "\r\n");
this.IDC_TEXT.ScrollToCaret();
Thread.Sleep(1000);
}
i = 999;
}
}
}
预想:界面上有一个文本框,用来显示递增的数字的(示例用)。还有两个按钮(START\STOP),按START启动工作者线程,按STOP停止工作者线程。
但是目前运行起来后,START可以启动线程,但是起来之后,界面就不能移动,点STOP也没反应了。
求教高手怎么解决这个问题。 展开
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WinPCapTest
{
public partial class Form1 : Form
{
static Boolean flag = false;
public Form1()
{
InitializeComponent();
}
private void IDC_NETCARD_Click(object sender, EventArgs e)
{
}
private void IDC_START_Click(object sender, EventArgs e)
{
flag = true;
Thread thread = new Thread(new ThreadStart(Test));
thread.IsBackground = true;
thread.Start(); }
private void IDC_STOP_Click(object sender, EventArgs e)
{
flag = false;
}
delegate void add();
public void Test()
{
this.BeginInvoke(new add(DoWork));
}
//工作者方法
public void DoWork()
{
int i = 0;
while (flag == true)
{
this.IDC_TEXT.AppendText((i++) + "\r\n");
this.IDC_TEXT.ScrollToCaret();
Thread.Sleep(1000);
}
i = 999;
}
}
}
预想:界面上有一个文本框,用来显示递增的数字的(示例用)。还有两个按钮(START\STOP),按START启动工作者线程,按STOP停止工作者线程。
但是目前运行起来后,START可以启动线程,但是起来之后,界面就不能移动,点STOP也没反应了。
求教高手怎么解决这个问题。 展开
4个回答
2015-10-17 · 知道合伙人数码行家
可以叫我表哥
知道合伙人数码行家
向TA提问 私信TA
知道合伙人数码行家
采纳数:25897
获赞数:1464972
2010年毕业于北京化工大学北方学院计算机科学与技术专业毕业,学士学位,工程电子技术行业4年从业经验。
向TA提问 私信TA
关注
展开全部
程序启动的时候会建立一个主线程,这个线程叫UI线程,从字面理解就可以知道这个线程专门处理有关UI(也就是界面)所有的事件。界面卡是因为,你进入了比如点击事件里面,线程一直在处理这个任务,这个任务一直没返回,也就是这个方法一直没返回。所以这个时候你点击界面是没反应的,也就是假死状态。
如果需要处理一个长时间的任务,应该建立一个新线程B去处理。同时B要去修改界面的话,需要用委托。因为界面是主线程负责,用委托是把修改界面这个动作交给主线程去做,如果由B去做的话可能会造成死锁之类问题
C#从另外一个线程操作windows窗体上的控件,必须要使用委托,通过委托调用UI线程去操控控件
//这个是窗体线程MainFrm
public delegate void Delegate_ChangeCallBack(string _value);
public Delegate_ChangeCallBack dlg_Change;
public static MainFrm mainFrm;
private void MainFrm_Load(object sender, EventArgs e)
{
mainFrm = this;
dlg_Change = new Delegate_ChangeCallBack (ChangeUI);
}
private void ChangeUI(string _value)
{
this.txt_Change.text = _value;
//do something...
}
private void button1_Click(object sender, EventArgs e)//下面是你的新线程
{
Client c = new Client();
Thread newThread = new Thread(new ParameterizedThreadStart(c.NewThread());
newThread.Name = "Door2 Conn Thread:" + mission.Id;
newThread.IsBackground = true;
newThread.Start();
}
Class Client
{
private void NewThread()
{
string _Id = "change";
MainFrm.mainFrm.BeginInvoke(MainFrm.mainFrm.dlg_Change , new object[] { _Id });
}
}
如果需要处理一个长时间的任务,应该建立一个新线程B去处理。同时B要去修改界面的话,需要用委托。因为界面是主线程负责,用委托是把修改界面这个动作交给主线程去做,如果由B去做的话可能会造成死锁之类问题
C#从另外一个线程操作windows窗体上的控件,必须要使用委托,通过委托调用UI线程去操控控件
//这个是窗体线程MainFrm
public delegate void Delegate_ChangeCallBack(string _value);
public Delegate_ChangeCallBack dlg_Change;
public static MainFrm mainFrm;
private void MainFrm_Load(object sender, EventArgs e)
{
mainFrm = this;
dlg_Change = new Delegate_ChangeCallBack (ChangeUI);
}
private void ChangeUI(string _value)
{
this.txt_Change.text = _value;
//do something...
}
private void button1_Click(object sender, EventArgs e)//下面是你的新线程
{
Client c = new Client();
Thread newThread = new Thread(new ParameterizedThreadStart(c.NewThread());
newThread.Name = "Door2 Conn Thread:" + mission.Id;
newThread.IsBackground = true;
newThread.Start();
}
Class Client
{
private void NewThread()
{
string _Id = "change";
MainFrm.mainFrm.BeginInvoke(MainFrm.mainFrm.dlg_Change , new object[] { _Id });
}
}
展开全部
因为你的界面的大部分时间被阻塞在sleep(1000)上了。
当线程调动后,你启用了BeginInvoke去执行DoWork时,DoWork函数即在当前界面所在线程执行工作了,只有当DoWork执行完毕后你的界面才得到执行的机会,这时才会有影应。
请不要在整个函数使用BeginInvoke或是invoke来调用,而应该在执行界面相关的操作的时候(比如对idc_text执行操作时)才使用BeginInvoke或是invoke。
当线程调动后,你启用了BeginInvoke去执行DoWork时,DoWork函数即在当前界面所在线程执行工作了,只有当DoWork执行完毕后你的界面才得到执行的机会,这时才会有影应。
请不要在整个函数使用BeginInvoke或是invoke来调用,而应该在执行界面相关的操作的时候(比如对idc_text执行操作时)才使用BeginInvoke或是invoke。
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
没有看明白你用多线程要实现什么效果?你声明DoWork()方法是在主线程执行的,不是在你声明的副线程中执行,那界面怎么会动呢?
你执行了一个副线程,起到的作用就是执行了Test()方法,没有停留就转到了主线程执行DoWork()方法了,实际效果:相当于点击开始执行的是DoWork()方法。
如果你想使用多线程实现数字隔一秒刷新一次,那么你的循环代码应该放到Test()方法中。
OK。
你执行了一个副线程,起到的作用就是执行了Test()方法,没有停留就转到了主线程执行DoWork()方法了,实际效果:相当于点击开始执行的是DoWork()方法。
如果你想使用多线程实现数字隔一秒刷新一次,那么你的循环代码应该放到Test()方法中。
OK。
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
实在想不明白你异步启动了一个Thread又调用BeginInvoke让代码在UI线程上同步执行是为什么……
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询