【发布时间】:2015-03-19 13:02:29
【问题描述】:
我有一个 winform 和一个不断发送更新的接口回调。我希望能够从回调接口更新 label1.Text。但是,由于接口在单独的线程上运行,我认为我不能直接执行此操作,因此我尝试使用委托并调用。
但是我遇到了一个错误:
在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke - at
form1.Invoke(form1.myDelegate, new Object[] { so.getString() });
这是完整的代码。
public partial class Form1 : Form
{
MyCallBack callback;
public delegate void UpdateDelegate(string myString);
public UpdateDelegate myDelegate;
public Form1()
{
InitializeComponent();
myDelegate = new UpdateDelegate(UpdateDelegateMethod);
callback = new MyCallBack(this);
CallBackInterfaceClass.SetCallBack(callback);
callback.OnUpdate();
}
public void UpdateDelegateMethod (String str)
{
label1.Text = str;
}
}
class MyTestCallBack : Callback
{
public Form1 form1;
public SomeObject so;
public MyTestCallBack(Form1 form)
{
this.form1 = form;
}
public void OnUpdate(SomeObject someobj)
{
so = someobj;
OnUpdate();
}
public void OnUpdate()
{
form1.Invoke(form1.myDelegate, new Object[] { so.getString() });
}
}
两个问题。
谁能解释我做错了什么?
这实际上是最好的方法吗?
这是基于 bokibeg 的回复(见下文)的答案,并进行了一些修改以使其正常工作:
public partial class Form1 : Form { MyTestCallBack _callback; public Form1() { InitializeComponent(); _callback = new MyTestCallBack(); _callback.MyTestCallBackEvent += callback_MyTestCallBackEvent; _callback.OnUpdate(); } private callback_MyTestCallBackEvent(MyTestCallBackEventArgs e) { if (InvokeRequired) { Invoke(new Action(() => { callback_MyTestCallBackEvent(sender, e); })); return; } label1.Text = e.SomeObject.GetDisplayString(); } class MyTestCallBackEventArgs : EventArgs { public SomeObject SomeObj { get; set; } } class MyTestCallBack : Callback { public event EventHandler<MyTestCallBackEventArgs> MyTestCallBackEvent; private SomeObject _so; protected virtual void OnMyTestCallBackEvent(MyTestCallBackEventArgs e) { if (MyTestCallBackEvent != null) MyTestCallBackEvent(this, e); } public void OnUpdate(SomeObject someobj) { _so = someobj; OnMyTestCallBackEvent(new MyTestCallBackEventArgs { SomeObject = _so }); } }
【问题讨论】:
-
如果我是你,我不会打电话给表单的代表,我会反其道而行之。
Callback派生类应该简单地引发一个事件,并且您的表单应该订阅该事件。我看不到MyTestCallBack的实例化位置,但如果它可能在Form1内,这使得您应该使用事件更加明显。编辑:好的,我看到它在哪里实例化了,是的,我肯定会从我的回调类中触发事件,而不是你在上面的代码中尝试的。
标签: c# multithreading winforms