C#异步调用,界面假死

这是一个测试的程序,界面上只有一个TEXTBOX,和一个button后台代码如图片点击按钮后界面假死,在textbox中无法显示“正在调用>>>>”的字样... 这是一个测试的程序,界面上只有一个TEXTBOX,和一个button
后台代码如图片

点击按钮后界面假死,在textbox中无法显示“正在调用>>>>”的字样
展开
 我来答
瘦成一导闪电呀
高粉答主

2015-11-19 · 每天分享健身知识,希望每位小仙女走路带风
瘦成一导闪电呀
采纳数:1266 获赞数:52260

向TA提问 私信TA
展开全部
方法如下:
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);
百度网友07da055
2011-09-02 · TA获得超过659个赞
知道小有建树答主
回答量:356
采纳率:33%
帮助的人:234万
展开全部
楼主这个问题的解决方法,可以使用多线程来完成。
举一个例子,楼主在窗体中放一个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()一下
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
百度网友d18ea0f
2011-09-02 · TA获得超过174个赞
知道小有建树答主
回答量:145
采纳率:0%
帮助的人:171万
展开全部
这是因为button1_Click(....)方法在处理时,UI不能进行重绘(UI重绘与button1_Click方法会在同一个线程中被调用),所以出现界面假死。

解决办法就是将整个while循环放到一个异步处理中(当前的while循环不是一个异步调用)。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
匿名用户
2011-09-02
展开全部
把sleep(1000) 换成这个:Application.DoEvents()
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式