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();
}
...全文
244 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 在哪里?
内容概要:本文系统研究了开关频率大于谐振频率(fs>fr)工况下,移相混合控制LLC谐振变换器在低压增益区域的工作特性,深入分析其在变频与移相结合控制模式下的调制机理、工作模态划分及损耗分布规律。通过Simulink平台构建高保真仿真模型,对变换器在不同负载和输入条件下的电压增益、转换效率、关键器件电压电流应力等性能指标进行了全面仿真验证,重点探讨了其在低增益区的软开关实现能力与效率优化潜力,旨在提升LLC变换器在宽范围输入输出应用中的动态响应与能源转换效率。; 适合人群:从事电力电变换器设计、高频电源开发及相关领域的高校研究生、科研院所研究人员及企业研发工程师,要求具备扎实的电路理论基础、电力电技术知识以及一定的Simulink仿真能力。; 使用场景及目标:①深入理解LLC谐振变换器在fs>fr条件下采用移相混合控制的内在工作机理与模态转换过程;②掌握利用Simulink搭建复杂谐振变换器精确仿真模型的方法与技巧;③分析并优化低压增益区的增益特性与损耗构成,为设计高效率、高功率密度的软开关电源提供理论依据和数据支持; 阅读建议:建议读者结合文中所述仿真模型,亲自复现仿真过程,重点观察不同控制参数(如移相比、开关频率)对电压增益曲线和关键波形的影响,并对比传统变频控制策略,深入探究混合控制在拓宽调压范围、提升轻载效率方面的优势,从而深化对现代高效谐振电源设计的理解。
内容概要:本文提出了一种基于粒群优化算法(PSO)的配电网光伏储能双层优化配置模型,以IEEE33节点系统为标准算例,实现光伏发电单元与储能系统的协同选址与定容优化。该模型采用双层架构设计,上层以投资成本、运行经济性及网络损耗最小为目标优化设备配置方案,下层通过潮流计算评估系统在不同负荷场景下的运行性能,综合考虑电压稳定性、供电可靠性及可再生能源消纳能力,最终通过Matlab编程实现完整求解流程,为高渗透率分布式电源接入背景下的配电网规划提供了有效的技术支撑。; 适合人群:具备电力系统分析基础和Matlab编程能力的研究生、高校科研人员及从事新能源并网、智能配电网规划与优化的工程技术人员。; 使用场景及目标:①研究含高比例光伏接入的配电网规划与运行协同优化问题;②掌握双层优化建模方法与粒群算法在复杂电力系统问题中的应用技巧;③为实际工程中分布式光伏与储能系统的科学选址与容量配置提供理论依据与仿真验证平台。; 阅读建议:建议读者结合Matlab代码深入理解双层迭代求解机制,重点关注算法收敛性分析、参数敏感性测试,并可通过更换初始种群、调整权重因或引入其他标准测试系统(如IEEE69节点)进行对比实验,进一步验证所提模型的普适性与鲁棒性。

111,129

社区成员

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

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

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