我一直在努力学习代表。我刚刚创建了一个按钮,标签和复选框。如果单击复选框,则时间格式会更改。如果我单击按钮,我会相应地打印日期。但是,当尝试使用异步委托,即使用另一个线程时,我遇到了错误
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.
你可以帮我解决一下这个问题吗?
答案 0 :(得分:4)
您无法从不是表单线程的线程访问表单和控件属性和方法。
在Windows中,每个窗口都绑定到创建它的线程。
只能使用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);
}
我不知道为什么你需要一个异步回调来打印时间然而:)真的不知道为什么,认为它只是一些测试代码。