调用线程不能访问此对象,因为不同的线程拥有它

问题描述:

好吧,我当前的代码正在进行中,可能我会尝试使用Async CTP做同样的事情。但我仍然想知道发生了什么。调用线程不能访问此对象,因为不同的线程拥有它

我有HttpHelper@pastebin像下面

// In MainWindow.xaml.cs 
Task.Factory.StartNew(() => helper.Send()); 

// In class HttpHelper 
public void Send() 
{ 
    // ... 

    try 
    { 
     Status = Statuses.Uploading; 
     // write to request stream 

     Status = Statuses.Downloading; 
     // write to response stream 

     Status = Statuses.Idle; // the exception is thrown here 
     // ... 
    } 
    catch (Exception e) 
    { 
     // ... 
    } 
} 

完整的代码的功能。 Send() on line 76

我想知道为什么我会得到异常?也许我在线程方面做了一些错误,但为什么只有在成功设置Status属性两次后才会引发异常?

UPDATE:原因...

我有一个事件处理程序,听StatusChanged事件,在1 if语句,我忘了使用UI线程更新UI

helper.StatusChanged += (s, evt) => 
{ 
    _dispatcher.Invoke(new Action(() => txtStatus.Text = helper.Status.ToString())); // I used _dispatcher here correctly 

    if (helper.Status == HttpHelper.Statuses.Idle || helper.Status == HttpHelper.Statuses.Error) 
     progBar.IsIndeterminate = false; // but not here 
}; 
+0

因为有时你会得到UI线程,有时你不会...... – 2010-11-22 13:41:14

更新:我错过了(在我的防守,小)在您的代码中的评论,你放弃了使用WPF/Silverlight而不是Windows窗体。

不过,看起来你能够采取什么我说的基本精神,并将其应用到自己的情况适当地(使用Dispatcher.Invoke而不是Control.Invoke)-Well完成;)


我猜测附加到您的StatusChanged事件的事件处理程序会更新您的UI上的StatusLabel控件?如果是这种情况,那么你需要从UI线程调用Invoke;例如:

void HttpHelper_StatusChanged(object sender, EventArgs e) 
{ 
    var httpHelper = (HttpHelper)sender; 
    UpdateStatus(httpHelper.Status); 
} 

void UpdateStatus(HttpHelper.Statuses status) 
{ 
    if (InvokeRequired) 
    { 
     Invoke(new Action<HttpHelper.Statuses>(UpdateStatus), status); 
    } 
    else 
    { 
     // Your code probably doesn't look like this; 
     // it's just an example. 
     statusLabel.Text = status.ToString(); 
    } 
} 

你可能会看到两个成功后跟一个失败的原因有点超出我的意思;但我知道StatusLabel控件在涉及线程问题时尤其会有点回避。我已经看到代码在哪里直接从后台线程更新(通常由于开发人员的疏忽)而没有任何异常;它看起来像你刚刚幸运两次,不幸一次。

+1

虚拟-1。没有!!它是Dispatcher.Invoke()。这是WPF/SilverLight不是WPF。 – Aliostad 2010-11-22 13:48:41

+0

@Aliostad:好的呼叫;在这种情况下,我认为我看到了问题。我会更新(再次)... – 2010-11-22 13:53:18

+0

@Aliostad:呃... OP太聪明了,知道了。这让我的生活更轻松;) – 2010-11-22 14:00:02

如果Status是一个全局变量,你将会得到这个异常,因为多个线程同时访问和更新它。我建议使用它附近的锁

Status是否触摸用户界面?因为它看起来像。

我只能猜测,但我想Status改变了UI上需要通过Dispatcher.Invoke()完成的事情。