WinForm子窗口的事件传回父窗口,操作父窗口控件时提示:线程间操作无效: 从不是创建控件“btn_Login”的线程访问它。

张天星 2018-11-03 02:33:53
先看我的两个窗口代码:
/// <summary>
/// 子窗口
/// </summary>
public partial class FormCefSharp : Form
{
public event EventHandler UserNameChange;
private string UserName
{
get
{
return _userName;
}
set
{
_userName = value;
UserNameChange?.Invoke(value, null); //事件,传回父窗口
}
}
}

/// <summary>
/// 父窗口
/// </summary>
public partial class FormMain : Form
{
FormCefSharp formCefSharp;
public FormMain()
{
InitializeComponent();
FormCefSharpInit();
}
private void FormCefSharpInit()
{
formCefSharp = FormCefSharp.GetIntance;
formCefSharp.UserNameChange += new EventHandler(CefSharpUserNameChange);
}
public void CefSharpUserNameChange(object sender, EventArgs e)
{
//问题在这里,这里我使用了Invoke,来解决线程间操作无效的问题
//有没有办法不用Invoke,直接btn_Login.Text = sender.ToString();
//如果真的什么处理,这一步可以放到formCefSharp中么?
if (InvokeRequired)
{
Invoke(new EventHandler(CefSharpUserNameChange), sender, e);
return;
}
btn_Login.Text = sender.ToString();
}
}

//问题在这里,这里我使用了Invoke,来解决线程间操作无效的问题
//有没有办法不用Invoke,直接btn_Login.Text = sender.ToString();
//如果真的什么处理,这一步可以放到formCefSharp中么?
我想的是,将需要处理的事情,在子窗口中全部做好,父窗口直接做赋值操作可以么?
public void CefSharpUserNameChange(object sender, EventArgs e)
{
btn_Login.Text = sender.ToString();
}
...全文
164 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
张天星 2018-11-06
  • 打赏
  • 举报
回复
先结贴了,然后我整理整理,重新问个
xuzuning 2018-11-06
  • 打赏
  • 举报
回复
其实你始终都没有给出向 FormCefSharp.UserName 赋值的代码(事件是由此发生的)
小马快跑! 2018-11-06
  • 打赏
  • 举报
回复
你的委托写反了
loveljy_19901114 2018-11-05
  • 打赏
  • 举报
回复
这里的invoke应该是跨两个UI线程来操作控件的,我也不知道可不可以,一般是在UI线程和后台线程之间跨操作的话用这个
0 1看天下 2018-11-05
  • 打赏
  • 举报
回复
跨线程了 用事件 或者委托走
xuzuning 2018-11-04
  • 打赏
  • 举报
回复
    public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

var f = new Form2();
f.Show();
f.OnAddEvent += new EventHandler<AddEventData>(f_OnAddEvent);
}

void f_OnAddEvent(object sender, AddEventData e)
{
textBox1.Text = e.Text;
}
}

public class AddEventData : EventArgs
{
public string Text;
}


public partial class Form2 : Form
{
public event EventHandler<AddEventData> OnAddEvent;
public Form2()
{
InitializeComponent();

textBox1.TextChanged += new EventHandler(textBox1_TextChanged);
}

void textBox1_TextChanged(object sender, EventArgs e)
{
if (OnAddEvent != null)
{
OnAddEvent(this, new AddEventData() { Text = textBox1.Text });
}
}
}
不注释也能看的懂吧?
  • 打赏
  • 举报
回复
public void CefSharpUserNameChange(object sender, EventArgs e) { this.BeginInvoke((Action)delegate { btn_Login.Text = sender.ToString(); }); }
张天星 2018-11-04
  • 打赏
  • 举报
回复
引用 4 楼 qq_38613453 的回复:
可以把父窗体的对象传给子窗体,子窗体要操作父窗体可以把操作封装成一个可访问的方法!怎么传对象,可以在子窗体里写一个方法,把对象传过去,这样子窗体就可以操作父窗体!

可是,我们父窗口打开子窗口(控件),然后写一个事件方法,去委托给子窗口(控件)调用,这个顺序应该没错啊。
引用 4 楼 qq_38613453 的回复:
可以把父窗体的对象传给子窗体,子窗体要操作父窗体可以把操作封装成一个可访问的方法!怎么传对象,可以在子窗体里写一个方法,把对象传过去,这样子窗体就可以操作父窗体!

我以前就是这么写的,可是这样子窗体中必须有一个父窗体的变量,我感觉这样比较笨重,在父窗体不同的时候就很麻烦。
所以想改成子窗体发生事件,父窗体写一个方法委托进去响应。
张天星 2018-11-04
  • 打赏
  • 举报
回复
引用 6 楼 sp1234 的回复:
public void CefSharpUserNameChange(object sender, EventArgs e)
{
this.BeginInvoke((Action)delegate
{
btn_Login.Text = sender.ToString();
});
}

我在修改旧代码中,子窗口直接调用父窗口的对象,全部该成本事件传递之后,父窗口的响应事件都可以直接对控件赋值,我对比了一下,
这次问题中,Form2中触发事件的方法是一个异步方法,所以事件在Form1中响应的时候,就必须使用Invoke了。


引用 7 楼 xuzuning 的回复:
    public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

var f = new Form2();
f.Show();
f.OnAddEvent += new EventHandler<AddEventData>(f_OnAddEvent);
}

void f_OnAddEvent(object sender, AddEventData e)
{
textBox1.Text = e.Text;
}
}

public class AddEventData : EventArgs
{
public string Text;
}


public partial class Form2 : Form
{
public event EventHandler<AddEventData> OnAddEvent;
public Form2()
{
InitializeComponent();

textBox1.TextChanged += new EventHandler(textBox1_TextChanged);
}

void textBox1_TextChanged(object sender, EventArgs e)
{
if (OnAddEvent != null)
{
OnAddEvent(this, new AddEventData() { Text = textBox1.Text });
}
}
}
不注释也能看的懂吧?

多谢,可以看懂,你将传递的数据分装到EventArgs中,object传递的是自身对象,这个好像才是正确的事件传递,我会学着修改。
至于问题本身,我发现是因为触发事件的方法是异步方法的缘故,我其他窗口相互之间触发事件就不需要Invoke,可以直接赋值
嗯啦啦啦嗯 2018-11-03
  • 打赏
  • 举报
回复
可以把父窗体的对象传给子窗体,子窗体要操作父窗体可以把操作封装成一个可访问的方法!怎么传对象,可以在子窗体里写一个方法,把对象传过去,这样子窗体就可以操作父窗体!
失落的神庙 2018-11-03
  • 打赏
  • 举报
回复
你用父窗体的UI线程操作子窗体是不行的吧。应该是父窗体委托子窗体里的UI线程里操作。应该是写反了。
张天星 2018-11-03
  • 打赏
  • 举报
回复
引用 1 楼 xuzuning 的回复:
btn_Login 在哪里?

这是个button控件,在FormMain上。
xuzuning 2018-11-03
  • 打赏
  • 举报
回复
btn_Login 在哪里?

110,546

社区成员

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

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

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