CF 3.5 中的 Control.Invoke 委托
似乎每个人都注意到 CF 无法 Control.Invoke 除 EventHandler 类型之外的委托。我找到了几种方法来解决该问题并通过棘手的事件和属性捕获参数,但它仅适用于某些对象/基元。
问题是当我尝试发送 Control 时,程序在执行时抛出异常:“Control.Invoke 必须用于与在单独线程上创建的控件进行交互”,无论我检查 Control.IsInvokeRequired 并由处理程序槽跟踪Invoke 方法...见鬼,有一个片段:
static class Program
{
[MTAThread]
static void Main()
{
Form1 frm = new Form1();
frm.modifier = new CModifier(ref frm);
Application.Run(frm);
}
}
class CModifier
{
internal event EventHandler Modify;
internal CModifier(ref Form1 _frm)
{ frm = _frm; }
private Form1 frm;
internal void Start()
{
Thread t = new Thread(new ThreadStart(TestMe));
t.Start();
}
private void TestMe()
{
frm._current = new Label() { Text = "Try Me" };
Modify(this, EventArgs.Empty);
}
}
public partial class Form1 : Form
{
internal Form1()
{
InitializeComponent();
}
internal CModifier modifier;
internal Control _current;
private void Form1_Load(object sender, EventArgs e)
{
modifier.Modify += new EventHandler(modifier_Modify);
modifier.Start();
}
void modifier_Modify(object sender, EventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new EventHandler(modifier_Modify));
}
this.panel1.Controls.Add(_current);
}
}
我尝试了几乎所有可能的方法,但总是得到相同的结果。
我做错了什么? ---->有一个“回报”;调用后丢失。
无论如何,我的应用程序的实际错误(上面只是一个示例)是在这个过程中:
internal void ManageControls(RSSDecisionMaking.InterfaceBehaviour _behaviour, Control _control)
{
if (this.InvokeRequired)
{
this.Invoke((Action)delegate { ManageControls(_behaviour, _control); });
return;
}
switch (_behaviour)
{
case RSSDecisionMaking.InterfaceBehaviour.Display:
this.pnDisplayContainer.Controls.Clear();
this.pnDisplayContainer.Controls.Add(_control);
break;
case RSSDecisionMaking.InterfaceBehaviour.Command:
this.pnDisplayContainer.Controls.Clear();
this.pnDisplayContainer.Controls.Add(_control);
this.pnDisplayContainer.Controls[0].Focus();
break;
}
}
主要区别在于调用内容,我从另一个线程发送一个控件。
能告诉我它有什么区别吗?为什么这不起作用?
It seems like everybody have noticed CF is unable to Control.Invoke delegates other than EventHandler type. I found few ways to workaround the problem and catch the arguments trough tricky events and properties, but it works just for certain objects/primitives.
The problem is when I try to send a Control, the program throws an exception at execution time: "Control.Invoke must be used to interact with controls created on a separate thread" no matters that I checked Control.IsInvokeRequired and tracked by handler trough the Invoke method...what hell, there is the snipet:
static class Program
{
[MTAThread]
static void Main()
{
Form1 frm = new Form1();
frm.modifier = new CModifier(ref frm);
Application.Run(frm);
}
}
class CModifier
{
internal event EventHandler Modify;
internal CModifier(ref Form1 _frm)
{ frm = _frm; }
private Form1 frm;
internal void Start()
{
Thread t = new Thread(new ThreadStart(TestMe));
t.Start();
}
private void TestMe()
{
frm._current = new Label() { Text = "Try Me" };
Modify(this, EventArgs.Empty);
}
}
public partial class Form1 : Form
{
internal Form1()
{
InitializeComponent();
}
internal CModifier modifier;
internal Control _current;
private void Form1_Load(object sender, EventArgs e)
{
modifier.Modify += new EventHandler(modifier_Modify);
modifier.Start();
}
void modifier_Modify(object sender, EventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new EventHandler(modifier_Modify));
}
this.panel1.Controls.Add(_current);
}
}
I tried to do in almost every way possible and I always get the same result.
What am I doing wrong? ----> there is a "return;" lost after Invoke.
Anyway, te actual error at my app (above is just an example) is in this procedure:
internal void ManageControls(RSSDecisionMaking.InterfaceBehaviour _behaviour, Control _control)
{
if (this.InvokeRequired)
{
this.Invoke((Action)delegate { ManageControls(_behaviour, _control); });
return;
}
switch (_behaviour)
{
case RSSDecisionMaking.InterfaceBehaviour.Display:
this.pnDisplayContainer.Controls.Clear();
this.pnDisplayContainer.Controls.Add(_control);
break;
case RSSDecisionMaking.InterfaceBehaviour.Command:
this.pnDisplayContainer.Controls.Clear();
this.pnDisplayContainer.Controls.Add(_control);
this.pnDisplayContainer.Controls[0].Focus();
break;
}
}
The main difference is in the Invoke stuff, I'm sending a Control from another thread.
Could tell me what the difference it makes? Why this does not work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题很简单。您的
modifier_Modify
调用正确调用 Invoke,但随后它不会退出,而是继续向下并在ifControls.Add
code> 块(事实上,如果没有发生异常,Controls.Add
将被调用两次)。在this.Invoke
调用之后的if
块内插入一个return
。The issue is simple. Your
modifier_Modify
call calls Invoke properly, but then it doesn't exit, it continues down and callsControls.Add
in the thread context right after theif
block (in factControls.Add
would get called twice if the Exception didn't happen). Insert areturn
right after thethis.Invoke
call, inside theif
block.