C#异步调用,界面假死
这是一个测试的程序,界面上只有一个TEXTBOX,和一个button后台代码如图片点击按钮后界面假死,在textbox中无法显示“正在调用>>>>”的字样...
这是一个测试的程序,界面上只有一个TEXTBOX,和一个button
后台代码如图片
点击按钮后界面假死,在textbox中无法显示“正在调用>>>>”的字样 展开
后台代码如图片
点击按钮后界面假死,在textbox中无法显示“正在调用>>>>”的字样 展开
展开全部
方法如下:
lblStatus.Text = "执行中,请稍候……";
Func<int> longTask = new Func<int>(delegate()
{
// 模拟长时间任务
Thread.Sleep(2000);
// 返回任务结果:5
return 5;
});
// 发起一次异步调用,实际上就是在.net线程池中执行longTask
// 这时由于是其它线程在工作,UI线程未被阻塞,所以窗体不会假死
longTask.BeginInvoke(ar =>
{
// 使用EndInvoke获取到任务结果(5)
int result = longTask.EndInvoke(ar);
// 使用Control.Invoke方法将5显示到一个label上,如果没有Invoke,
// 直接写lblStatus.Text="5",将会抛出跨线程访问UI控件的异常
Invoke(new Action(() => lblStatus.Text = "执行结果是:" + result));
}, null);
展开全部
楼主这个问题的解决方法,可以使用多线程来完成。
举一个例子,楼主在窗体中放一个lable控件,写一个for循环,将lable的值从0开始赋值,每一秒值加1。但是不管你逻辑再好,只要你这段代码放在主线程了,那么窗体都会出现假死状态,直到循环完成才会恢复,而最后你也只能看到lable的最后一个值。
解决这个办法,就需要使用多线程来实现,具体用法参考如下:
//子线程将执行的方法
public void a()
{}
//声明子线程
Thread t = new Thread(new ThreadStart(a)); //声明子线程时,他所执行的方法必须是无参数的,同时不用写括号
//子线程开始
t.Start();
根据楼主的情况,楼主可以将a()看做改变strb值的方法,声明子线程、开始子线程,都写在那个button点击事件里。
但是,要特别说明,如果楼主在子线程中,改变主线程的控件,编译时可能会报错。所以要用到委托。给楼主写一段实例代码。
//定义一个委托,用来改变控件的属性。全局变量
private delegate void delegate1();
private delegate1 d1;
//定义子线程,用于执行方法
private Thread t;
//定义字符串,用于记录lable控件的显示值。全局变量
private String state = “正在调试中”;
//定义布尔值,用于记录子线程状态。全局变量
private bool isStart = false;
//用于显示状态
public void ShowStateDelegate()
{
lable1.text=state;
}
public void ShowState()
{
while(isStart)
{
Thread.Sleep(1000);
state +=">>";
this.Invoke(d1);
}
if(!isStart)
{
state +="执行完成";
this.Invoke(d1);
}
}
Button点击事件下
d1 = new delegate1(ShowStateDelegate);
t = new Thread(new ThreadStart(ShowState));
t.Start();
纯手写代码,可能有错,不过大体逻辑就是这样的。
举一个例子,楼主在窗体中放一个lable控件,写一个for循环,将lable的值从0开始赋值,每一秒值加1。但是不管你逻辑再好,只要你这段代码放在主线程了,那么窗体都会出现假死状态,直到循环完成才会恢复,而最后你也只能看到lable的最后一个值。
解决这个办法,就需要使用多线程来实现,具体用法参考如下:
//子线程将执行的方法
public void a()
{}
//声明子线程
Thread t = new Thread(new ThreadStart(a)); //声明子线程时,他所执行的方法必须是无参数的,同时不用写括号
//子线程开始
t.Start();
根据楼主的情况,楼主可以将a()看做改变strb值的方法,声明子线程、开始子线程,都写在那个button点击事件里。
但是,要特别说明,如果楼主在子线程中,改变主线程的控件,编译时可能会报错。所以要用到委托。给楼主写一段实例代码。
//定义一个委托,用来改变控件的属性。全局变量
private delegate void delegate1();
private delegate1 d1;
//定义子线程,用于执行方法
private Thread t;
//定义字符串,用于记录lable控件的显示值。全局变量
private String state = “正在调试中”;
//定义布尔值,用于记录子线程状态。全局变量
private bool isStart = false;
//用于显示状态
public void ShowStateDelegate()
{
lable1.text=state;
}
public void ShowState()
{
while(isStart)
{
Thread.Sleep(1000);
state +=">>";
this.Invoke(d1);
}
if(!isStart)
{
state +="执行完成";
this.Invoke(d1);
}
}
Button点击事件下
d1 = new delegate1(ShowStateDelegate);
t = new Thread(new ThreadStart(ShowState));
t.Start();
纯手写代码,可能有错,不过大体逻辑就是这样的。
更多追问追答
追问
这位大侠,你是再开一个进程来控制显示的。而控件在主线程上,这样跨线程操作,好像有点问题!
追答
先纠正楼主一个错误,这个是多线程,不是进程。
跨线程操作控件,正确的做法就是使用委托,我已经写了注释了,你可以看到,实例化委托的时候,我将ShowStateDelegate作为参数传入的,而ShowStateDelegate方法就是显示字符串内容。同时修改控件值的时候,我用了Invoke方法来实现的。
不过要提醒楼主,当你结束主线程的时候,如果子线程没完成,他回继续运行,所以在主线程结束的时候,需要先Application.ExitThread()一下
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
这是因为button1_Click(....)方法在处理时,UI不能进行重绘(UI重绘与button1_Click方法会在同一个线程中被调用),所以出现界面假死。
解决办法就是将整个while循环放到一个异步处理中(当前的while循环不是一个异步调用)。
解决办法就是将整个while循环放到一个异步处理中(当前的while循环不是一个异步调用)。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
2011-09-02
展开全部
把sleep(1000) 换成这个:Application.DoEvents()
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询