请教Winform:何如跨线程调用Windows控件?

mohugomohu 2009-01-21 10:57:55

public class TankClient : Form
{
int xPos = 30;
int yPos = 30;
public static void Main()
{
TankClient tc = new TankClient();
tc.LaunchForm();
}
protected void LaunchForm()
{
this.Size = new Size(800, 600);
Thread t = new Thread(new ThreadStart(Run));
t.Start();
this.ShowDialog();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
SolidBrush sb=new SolidBrush(Color.Red);
g.FillEllipse(sb,xPos, yPos,50,50);
}
private void Run()
{
while (true)
{
yPos += 5;
Thread.Sleep(50);
//怎么重画?
}
}
}

我想复习一下C#,现在想实现的是:在窗体上画个圆,每隔一段时间改变这个圆的位置.
...全文
624 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhaoyang22 2009-01-21
  • 打赏
  • 举报
回复
其实道理很简单,你也知道这个是跨线程调用控件的,WinForm里的控件只可以由创建这个控件的线程去使用,我们所看到的窗体界面是由一个窗体线程管理的,若要操作它的控件就要把要做到是委托给它,让它去做这件事,这就需要使用到代理,窗体线程拿到这个代理方法后就可以去执行了,这就有了下面一段代码:

//重绘代理
private delegate void RefreshDele();
//重载一下重绘方法
public override void Refresh()
{
if (!this.IsDisposed && this.InvokeRequired)
{
//调用反射方法
this.Invoke(new RefreshDele(Refresh));
}
else
{
base.Refresh();
}
}

PS:这么做的道理也很好理解,举个例子讲:假设你是研发部的小喽罗,如果市场部经理看你不爽,他不能直接训你,他要把情况反映到你们研发部经理那,让你们研发部的经理训你,^_^
mohugomohu 2009-01-21
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zhaoyang22 的回复:]
C# codepublic partial class Form1 : Form
{
int xPos = 30;
int yPos = 30;

//线程定义
Thread t = null;

public Form1()
{
InitializeComponent();
}

protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
SolidBrush sb = new SolidBrush(Color.Red);

[/Quote]
的确能实现,不过我都不明白是什么意思.
Dobzhansky 2009-01-21
  • 打赏
  • 举报
回复
通用的 delegate 调用, 来自 Programming .NET Components 一书

static void InvokeDelegate(Delegate del, object[] args)
{
ISynchronizeInvoke synchronizer = del.Target as ISynchronizeInvoke;
if (synchronizer != null)//Requires thread affinity
{
if (synchronizer.InvokeRequired)
{
synchronizer.Invoke(del, args);
return;
}
}
//Not requiring thread afinity or invoke is not required
del.DynamicInvoke(args);
}
HDNGO 2009-01-21
  • 打赏
  • 举报
回复
Control.CheckForIllegalCrossThreadCalls = false;
zhaoyang22 2009-01-21
  • 打赏
  • 举报
回复
public partial class Form1 : Form
{
int xPos = 30;
int yPos = 30;

//线程定义
Thread t = null;

public Form1()
{
InitializeComponent();
}

protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
SolidBrush sb = new SolidBrush(Color.Red);
g.FillEllipse(sb, xPos, yPos, 50, 50);
}

private void Run()
{
while (true)
{
yPos += 5;
Thread.Sleep(50);
//怎么重画?
this.Refresh();
}
}

//重绘代理
private delegate void RefreshDele();
//重载一下重绘方法
public override void Refresh()
{
if (!this.IsDisposed && this.InvokeRequired)
{

this.Invoke(new RefreshDele(Refresh));
}
else
{
base.Refresh();
}
}

private void Form1_Load(object sender, EventArgs e)
{
//启动线程
this.Size = new Size(800, 600);
t = new Thread(new ThreadStart(Run));
t.Start();
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//关闭线程
if (t.ThreadState != ThreadState.Stopped)
{
t.Abort();
}
}

}
68435970 2009-01-21
  • 打赏
  • 举报
回复
       public delegate void dTest();
void invokeThread()
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Reset();
sw.Start();
if (this.InvokeRequired)
{
this.Invoke(new dTest(CreateTreeView));
}
else
{
CreateTreeView();//方法名
}
sw.Stop();
}
ChrisAK 2009-01-21
  • 打赏
  • 举报
回复
跨线程操作空间要使用Invoke.
vrhero 2009-01-21
  • 打赏
  • 举报
回复
使用委托...
mohugomohu 2009-01-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zgke 的回复:]
//怎么重画?

加这个 Refresh();
[/Quote]
就是出错啊:线程间操作无效: 从不是创建控件“”的线程访问它。

唉,平时我都是直接建WindowsApplication然后拖控件,现在想自己写,发现什么都不会。
zgke 2009-01-21
  • 打赏
  • 举报
回复
//怎么重画?

加这个 Refresh();

111,131

社区成员

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

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

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