关于线程刷新窗体的问题(Invoke)

LIZHIztt 2009-11-29 11:38:56
做多线程通知窗体进行刷新,发现很麻烦,因为如果需要刷新的控件有很多的话,就需要写很多个委托,所以自己封装了一下,但是没成功,代码如下

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;

namespace WindowsApplication2
{
class CreateFile : System.Windows.Forms.Form
{

private string _FilePath = "";//创建文件目录

public delegate void FileCreate();
public delegate void FileCreateprogress(int sum, int current);


public event FileCreate FileError;//错误事件
public event FileCreate FileDone;//成功事件
public event FileCreateprogress FileProgress;//通知事件


public CreateFile(string FilePath)//构造函数
{
_FilePath = FilePath;
}


public void StartCreate()//开启线程创建文件
{
Thread TempThread = new Thread(new ThreadStart(_StartCreate));
TempThread.IsBackground=true;
TempThread.Start();

}

private void _StartCreate()//创建文件
{
for (int i = 0; i < 1000; i++)
{
try
{
FileStream TempFileStream = new FileStream(_FilePath + i + ".txt", FileMode.Create);
TempFileStream.Close();

if (FileProgress != null)//通知事件
{

FileCreateprogress filecreate_progress = new FileCreateprogress(FileProgress);
this.Invoke(filecreate_progress, new object[] { 100, i });
}
}
catch
{
if (FileError != null)//错误事件
{

FileCreate filecreate_error = new FileCreate(FileError);
this.Invoke(filecreate_error);
}
}

if (FileDone != null)//完成事件
{

FileCreate filecreate_done = new FileCreate(FileDone);
this.Invoke(filecreate_done);
}
}
}




}
}





调用方法如下

private void button1_Click(object sender, EventArgs e)
{

CreateFile createfile = new CreateFile(@"C:\temp\");
createfile.FileDone += new CreateFile.FileCreate(createfile_FileDone);
createfile.FileError += new CreateFile.FileCreate(createfile_FileError);
createfile.FileProgress += new CreateFile.FileCreateprogress(createfile_FileProgress);
createfile.StartCreate();
}

void createfile_FileProgress(int sum, int current)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = sum;
progressBar1.Value = current;
}

void createfile_FileError()
{
MessageBox.Show("生成发生错误");
}

void createfile_FileDone()
{
MessageBox.Show("生成完毕");
}




一执行就报异常 “在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。”,不明白是怎么回事. 对线程不是很了解,在此请教一下,

想要实现的效果就像许多自定义控件一样,里面用多线程执行一些操作,在通知事件里面直接写操作界面控件的代码就可以,不用写委托



...全文
558 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
starj1 2009-11-30
  • 打赏
  • 举报
回复
直接刷新控件所在的Form就可以了。一般Container刷新时,里面的子控件会跟着刷新的。
hyfzz123 2009-11-30
  • 打赏
  • 举报
回复
if (!Form.IsHandleCreated)
{
while (!Progress.IsHandleCreated)
{
;
}
}

上次也碰到楼主一样的问题,看看这个能解决不
flyerwing 2009-11-30
  • 打赏
  • 举报
回复
invoke
zzxap 2009-11-30
  • 打赏
  • 举报
回复
只有.NET里的form对象调用某种方法使系统产生真正的窗体时,form才会有创建它的线程的信息,且InvokeRquired才有效,即才能调用form的Invoke方法。。据我所知Show, CreateGraphics可以产生系统真正的系统窗体。
zzxap 2009-11-30
  • 打赏
  • 举报
回复
要等窗口创建完毕才能Invoke
biny101 2009-11-30
  • 打赏
  • 举报
回复
UP
CCppMfc 2009-11-30
  • 打赏
  • 举报
回复
如果非要这么做.

让 "调用方法如下"所在的Form 继承 CreateFile 呗.
gomoku 2009-11-30
  • 打赏
  • 举报
回复
更正14楼:
class CreateFile : System.Windows.Forms.Form
gomoku 2009-11-30
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 41756620 的回复:]
BackgroundWorker 在我这边做开发的时候是不允许是用的

有没有别的办法
[/Quote]

我刚刚看了你的另外一个贴子,才知道你是要Windows CE开发。
建议下次讲清楚环境,可以节约朋友们的时间。

如果没有BackgroundWorker,你至少可以传一个控件(Form也是控件)进去。


class CreateFile : System.Windows.Forms.Form
{
Control contextControl;
public CreateFile(string FilePath, Control context)
{
_FilePath = FilePath;
this.contextControl = context;
}

{
...
contextControl.Invoke(filecreate_progress, new object[] { 100, i });
}
}

private void button1_Click(object sender, EventArgs e)
{
CreateFile createfile = new CreateFile(@"C:\temp\", this);
...
}
wartim 2009-11-30
  • 打赏
  • 举报
回复
invoke
wartim 2009-11-30
  • 打赏
  • 举报
回复
CreateFile : System.Windows.Forms.Form

你这个类和form 有什么关系?为什么要从form继承?

必须主form 执行完InitializeComponent();和Shown后才能用invode
nashina 2009-11-30
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 lianshaohua 的回复:]
1、没有必要从form继承,
2、在线程中触发事件时,先取得已打开的第一个窗体,Application.OpenForms.invoke().....好像是这样来着,有多种方式,然后在主线程中invoke()这样就把线程的事件invoke到了主线程触发
[/Quote]
嗯嗯
zenjj 2009-11-30
  • 打赏
  • 举报
回复
顶一个
ztenv 2009-11-30
  • 打赏
  • 举报
回复
1、没有必要从form继承,
2、在线程中触发事件时,先取得已打开的第一个窗体,Application.OpenForms.invoke().....好像是这样来着,有多种方式,然后在主线程中invoke()这样就把线程的事件invoke到了主线程触发
lovelan1748 2009-11-30
  • 打赏
  • 举报
回复
帮顶
LIZHIztt 2009-11-30
  • 打赏
  • 举报
回复
BackgroundWorker 在我这边做开发的时候是不允许是用的

有没有别的办法
liherun 2009-11-30
  • 打赏
  • 举报
回复
学习
netstray 2009-11-30
  • 打赏
  • 举报
回复
顶一下,学习
angel6709 2009-11-30
  • 打赏
  • 举报
回复
学习、、
gomoku 2009-11-30
  • 打赏
  • 举报
回复
1、不能单单为了用this.Invoke而去继承Form。
2、你的问题用BackgroundWorker能更好的得到解决:[url=http://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker.aspx]BackgroundWorker 类[url]


this.Invoke的原理是比较当前的线程ID和创建this的线程(一般是UI线程)的线程ID。
如果他们不一样,就将委托送到目标UI线程执行。

检查线程ID的时候用到了GetWindowThreadProcessId API,该API需要一个窗口句柄。这就要求this(或this的父亲等)的窗口句柄已经创建了。
加载更多回复(4)

111,121

社区成员

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

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

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