c#线程问题:线程间操作无效:从不是创建控件picMonster1的线程访问它InvalidOperationException异常

c#线程问题:线程间操作无效:从不是创建控件picMonster1的线程访问它InvalidOperationException异常//创建线程privatevoidbt... c#线程问题:线程间操作无效:从不是创建控件picMonster1的线程访问它InvalidOperationException异常

//创建线程
private void btnMonsterAttack_Click(object sender, EventArgs e)
{

thread1 = new Thread(new ThreadStart(MonsterPkHero));
thread1.Name = monster1.MonsterName;
thread2 = new Thread(new ThreadStart(MonsterPkHero));
thread2.Name = monster2.MonsterName;
thread3 = new Thread(new ThreadStart(MonsterPkHero));
thread3.Name = monster3.MonsterName;

thread1.Start();
thread2.Start();
thread3.Start();
}

//线程调用的方法
public void MonsterPkHero()
{
lock (this)
{
string name = Thread.CurrentThread.Name;
foreach (TurtleMonster monster in listMonster)
{

if (name == monster.MonsterName)
{

string message = null;
monster.Move(hero);
UpdateUI(monster);
message = monster.Attack(hero);
this.lblMessage.Text = message;
UpdateUI(monster);
Thread.Sleep(1000);
monster.Move();
UpdateUI(monster);
Thread.Sleep(1000);

}

}
}

}

//上边方法调入的方法,也就是出现异常的地方
private void UpdateUI(TurtleMonster monster)
{

//怪物
//移动到当前位置

this.picHero.Location = hero.CurrentLocation;
//CheckForIllegalCrossThreadCalls = false;
monster.PictureBoxName.Location = monster.CurrentLocation; //在这句代码出出现的异常
//玩家生命值变化条
this.lblHeroCurBlood.Width = hero.CurrentBlood;
this.lblHeroCurBlood.Height = 20;
//怪物生命值变化条
monster.CurrentLabelName.Width = monster.CurrentBlood;
monster.CurrentLabelName.Height = 20;

if (monster.CurrentBlood == 0)
{
this.picHero.Image = Image.FromFile("heroDead.gif");
MessageBox.Show("英雄已死亡,游戏结束");
this.Dispose();
}
}

请问为什么会这样,应如何解决?
regnad朋友,你得回答我得看头疼...能不能再简洁点回答..谢谢....
展开
 我来答
regnad
2008-06-09 · TA获得超过532个赞
知道小有建树答主
回答量:345
采纳率:100%
帮助的人:187万
展开全部
在有些情况下,您可能需要通过线程调用控件的方法。例如,您可能要在窗体上调用一个禁用按钮或更新显示的方法来响应某个线程执行的操作。.NET Framework 提供从任何线程都可安全调用的方法,以调用与其他线程所拥有的控件进行交互的方法。Invoke 方法允许同步执行控件上的方法,而 BeginInvoke 方法则初始化异步执行。要使用这些方法,必须用与将调用的方法相同的签名声明委托。然后,您可以通过向要调用的方法提供适当的委托来调用窗体上任何控件的 Invoke 或 BeginInvoke 方法。任何必需的参数都包装在 Object 中,并被传输到该方法。

调用涉及其他线程所拥有的控件的方法
用与要调用的方法相同的签名声明一个委托。

下面的示例显示如何使用 Integer 和 String 参数声明委托。
调用涉及其他线程所拥有的控件的方法
用与要调用的方法相同的签名声明一个委托。

下面的示例显示如何使用 Integer 和 String 参数声明委托。

>Visual Basic

Public Delegate Sub myDelegate(ByVal anInteger as Integer, ByVal _
aString as String)

>C#
public delegate void myDelegate(int anInteger, string aString);

使用任何控件来调用对其他线程所拥有的控件进行操作的方法。

注意:
方法所需的参数(如果有)可在 Object 中提供。

如果要同步调用方法,请调用 Control.Invoke 方法。

>Visual Basic
Label1.Invoke(New myDelegate(AddressOf myMethod), New _
Object() {1, "This is the string"})

>C#
Label1.Invoke(new myDelegate(myMethod), new Object[] {1,
"This is the string"});

如果要异步调用方法,请调用 Control.BeginInvoke 方法。

>Visual Basic
Label1.BeginInvoke(New myDelegate(AddressOf myMethod), _
New Object() {1, "This is the string"})

>C#
Label1.BeginInvoke(new myDelegate(myMethod), new
Object[] {1, "This is the string"});

-----------------------------
举个例子:新建一个Windows应用程序项目Win1,在窗体Form1中添加一个Button名称为button1,然后转入代码页,按下面修改代码
using System;
using System.Windows.Forms;

namespace win1
{
public partial class Form1 : Form
{
public delegate void 我的委托();//声明一个委托
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)//此处先双击button1以便产生代码并且自动创建事件委托
{
new System.Threading.Thread(new System.Threading.ThreadStart (新线程)).Start();//创建一个新的线程并启动

}
public void 设置文字()
{
button1.Text = "Hello";
}

public void 新线程()
{
System.Threading.Thread.Sleep(2000);//线程休眠2秒
button1.BeginInvoke(new 我的委托(设置文字));//在button1所在线程上执行“设置文字”

}

}
}
运行:单击button1,两秒之后文字发生变化
ioucxj
2008-06-10 · 超过53用户采纳过TA的回答
知道答主
回答量:147
采纳率:0%
帮助的人:136万
展开全部
因为线程所调用的对象生命周期不存在此线程中

所调用的控件是另一个线程所创建的,所以,线程可以调用它所创建的控件,而不是其他控件所声明的
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

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

类别

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

说明

0/200

提交
取消

辅 助

模 式