请问一个关于执行for比较卡的问题

yunhaiC QQ654777694 2009-04-21 02:53:03
我在mouse_down里面执行了一个for循环,里面有延迟,比如每执行一次for就停2秒
但是在for没执行完毕的时候
整个form窗口就好卡,不能点其他button,必须等for执行完毕才可以点其他button

怎么解决这个问题?
...全文
96 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
蓝海D鱼 2009-04-21
  • 打赏
  • 举报
回复
对Windows窗体控件的线程安全调用

对窗体控件的线程安全调用需要用委托的方式。

主要思路:

1、查询控件的 InvokeRequired 属性。

2、如果 InvokeRequired 返回 true,则使用实际调用控件的委托来调用 Invoke。

3、如果 InvokeRequired 返回 false,则直接调用控件。

例子:在TextBox控件中输出相应的信息,SetText为textbox的内容设置方法,SetTextDelegate的委托类型封装 SetText方法。TextBox控件的InvokeRequired返回true是,SetText方法创建SetTextDelegate的一个实例,并调用窗体的Invoke方法。是的SetText方法被创建TextBox控件的线程调用。



// 该事件句柄创建一个对窗体控件线程安全调用的线程



private void setTextSafeBtn_Click( object sender, EventArgs e)
{
this.demoThread =
new Thread(new ThreadStart(this.ThreadProcSafe));

this.demoThread.Start();
}

// 该方法在Worker线程中执行并且发出一个线程安全的调用

private void ThreadProcSafe()
{
this.SetText("This text was set safely.");
}

//如果被调用的线程和创建的TextBox控件不同,该方法就创建一个SetTextCallback,

// 并且用Invoke方法异步调用自己。
// 如果相同,则直接调用方法设置Text的属性。

private void SetText(string text)
{
// 获取的InvokeRequired将调用的线程ID和创建的线程ID向比较。
//如果两个线程ID不同,则返回true

if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] ...{ text });
}
else
{
this.textBox1.Text = text;
}
}
Fy_Hello 2009-04-21
  • 打赏
  • 举报
回复
好强哦,楼上的几位.我也学到了点,谢谢
wonture 2009-04-21
  • 打赏
  • 举报
回复
线程调用控件,定义一个委托吧。通过委托去调用控件就是了。
abcfy2 2009-04-21
  • 打赏
  • 举报
回复
简单来说一下吧,我接触WINFORM编程也不久,这些问题我还是遇到过的。
因为for循环中,执行量比较大的时候,CPU会使用较多的时间来处理for循环的数据,那么就会使主线程中的窗体假死,暂时无响应,得等for循环处理完毕以后,窗体才能重新得到响应。
因此解决方法就是使用多线程处理,线程是通过时间片方式轮流抢占CPU的,所以可以解决在计算大量的数据的时候主窗体假死的现象。
但是多线程就会有同步访问同一个资源的现象,如果不加处理可能造成假死或者饥饿现象。(学过操作系统的话应该清楚这一点)
因此WINFORM在建立的时候会检查是否是创建的线程在访问该窗体的控件.
窗体运行的时候,可以看做一个独立的线程开始执行,WINFORM开始检测是否有其他的线程在访问主线程的控件,如果有,就会抛出异常“线程间操作无效: 从不是创建控件。。。的线程访问它”
解决的方法最好是互斥访问,就是Invoke()方法。
当然还有鸵鸟政策,就是6楼说的方法,让WINFORM不禁止多线程同步访问控件,但是这样的话,就得你自己控制好代码了,尽量不要让多个线程同时去操控一个控件。
ericzhangbo1982111 2009-04-21
  • 打赏
  • 举报
回复
你要调用窗体里的控件的话 需要invoke一下
Garnett_KG 2009-04-21
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 deyter 的回复:]
请问楼上两位
用线程操作有时为什么会出现“线程间操作无效: 从不是创建控件。。。的线程访问它?

[/Quote]

这个要用delegate去更新ui的控件.
或者干脆在Form_Load的地方加一句
CheckForIllegalCrossThreadCalls = false;
wb186 2009-04-21
  • 打赏
  • 举报
回复
恩,重新开一个线程去做
deyter 2009-04-21
  • 打赏
  • 举报
回复
请问楼上两位
用线程操作有时为什么会出现“线程间操作无效: 从不是创建控件。。。的线程访问它?
Garnett_KG 2009-04-21
  • 打赏
  • 举报
回复
在mouse_down里的代码用ThreadPool执行
ex:


protected override void mosue_down(....)
{
ThreadPool.QueueUserWorkItem(o =>
{
//你原来的代码
});
}


yangqidong 2009-04-21
  • 打赏
  • 举报
回复
使用新线程去执行循环
ericzhangbo1982111 2009-04-21
  • 打赏
  • 举报
回复
可以用以个线程来执行你的操作
Thread t = new Thread(new ThreadStart(Run));
t.Start();


public void Run()
{

}

111,125

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧