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朋友,你得回答我得看头疼...能不能再简洁点回答..谢谢.... 展开
//创建线程
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朋友,你得回答我得看头疼...能不能再简洁点回答..谢谢.... 展开
2个回答
展开全部
在有些情况下,您可能需要通过线程调用控件的方法。例如,您可能要在窗体上调用一个禁用按钮或更新显示的方法来响应某个线程执行的操作。.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,两秒之后文字发生变化
调用涉及其他线程所拥有的控件的方法
用与要调用的方法相同的签名声明一个委托。
下面的示例显示如何使用 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,两秒之后文字发生变化
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询