我有一个winform和一个接口回调,不断发送更新。我希望能够从回调接口更新label1.Text。但是,由于接口在单独的线程上运行,因此我认为无法直接执行此操作,因此我尝试使用委托和invoke。
然而,我遇到了一个错误:
在窗口句柄创建之前,无法在控件上调用Invoke或BeginInvoke - 在
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
中被实例化,那么你就更应该使用事件。编辑:好的,我看到它在哪里被实例化了,所以是的,我肯定会从我的回调类中触发事件,而不是你试图在上面的代码中做的事情。 - bokibeg