跨线程操作无效:异步委托错误

时间:2011-11-02 03:15:35

标签: c#

我一直在努力学习代表。我刚刚创建了一个按钮,标签和复选框。如果单击复选框,则时间格式会更改。如果我单击按钮,我会相应地打印日期。但是,当尝试使用异步委托,即使用另一个线程时,我遇到了错误

   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.

你可以帮我解决一下这个问题吗?

1 个答案:

答案 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);
    }

我不知道为什么你需要一个异步回调来打印时间然而:)真的不知道为什么,认为它只是一些测试代码。