跨线程操作无效:异步委托错误
本文关键字:错误 异步 线程 操作 无效 | 更新日期: 2023-09-27 18:13:08
我一直在努力学习委托。我刚刚创建了一个按钮、标签和复选框。单击"复选框"后,时间格式会发生变化。如果我点击按钮,我打印相应的日期。然而,当尝试使用异步委托,即使用另一个线程,我卡住了一个错误
public delegate void AsyncDelegate(bool seconds);
public partial class Form1 : Form
{
AsyncDelegate ad;
TimeZ t = new TimeZ();
public Form1()
{
InitializeComponent();
}
private void btn_async_Click(object sender, EventArgs e)
{
ad = new AsyncDelegate(t.GetTime);
AsyncCallback acb = new AsyncCallback(CB);
if (chk_sec.Checked)
{
ad.BeginInvoke(true, acb, null);
}
else
ad.BeginInvoke(false, acb, null);
}
public void CB(IAsyncResult ar)
{
t.Tim = ar.ToString();
ad.EndInvoke(ar);
lbl_time.Text = t.Tim;
}
和在另一个类库中,我得到上面使用的Timez。我在项目中添加了它的引用
public class TimeZ
{
private string tim;
public string Tim
{
get
{
return tim;
}
set
{
tim = value;
}
}
public string GetTime(bool seconds)
{
if (seconds)
{
return DateTime.Now.ToLongTimeString();
}
else
return DateTime.Now.ToShortTimeString();
}
}
然而,当我运行程序时,我得到这个错误:
Cross-thread operation not valid: Control 'lbl_time' accessed from a thread other than
the thread it was created on.
你能告诉我怎么解决这个问题吗?
您不能从非表单线程访问表单和控件的属性和方法。
在窗口中,每个窗口都绑定到创建它的线程。
您只能在Control中这样做。BeginInvoke或更有用的System.Threading.SynchronizationContext类
见http://msdn.microsoft.com/it-it/library/system.threading.synchronizationcontext (v = vs.95) . aspx
见http://msdn.microsoft.com/it-it/library/0b1bf3y3 (v = vs.80) . aspx
这意味着,你必须通过同步上下文发布,例如在表单线程中另一个异步委托。
public partial class Form1 : Form
{
AsyncDelegate ad;
TimeZ t = new TimeZ();
// Our synchronization context
SynchronizationContext syncContext;
public Form1()
{
InitializeComponent();
// Initialize the synchronization context field
syncContext = SynchronizationContext.Current;
}
private void btn_async_Click(object sender, EventArgs e)
{
ad = new AsyncDelegate(t.GetTime);
AsyncCallback acb = new AsyncCallback(CB);
if (chk_sec.Checked)
{
ad.BeginInvoke(true, acb, null);
}
else
{
ad.BeginInvoke(false, acb, null);
}
}
public void CB(IAsyncResult ar)
{
// this will be executed in another thread
t.Tim = ar.ToString(); // ar.ToString()???? this will not give you the time for sure! why?
ad.EndInvoke(ar);
syncContext.Post(delegate(object state)
{
// This will be executed again in form thread
lbl_time.Text = t.Tim;
}, null);
}
我不知道为什么你需要一个异步回调来打印时间,但是:)真的不知道为什么,认为这只是一些测试代码。