[英]The calling thread cannot access this object because a different thread owns it
Ok, my current code is work in progress and probably I will try to do the same thing with the Async CTP. 好的,我当前的代码正在开发中,可能我将尝试使用异步CTP做同样的事情。 But I will still like to understand whats happening. 但是我仍然想了解发生了什么。
I have a function like below 我有一个像下面的功能
// 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)
{
// ...
}
}
Full Code for HttpHelper
@pastebin . HttpHelper
@pastebin的完整代码。 Send()
on line 76 第76行的Send()
I wonder why I get the exception? 我想知道为什么我会得到例外? Maybe I did something wrong with the threading, but why is the exception raised only after I successfully set the Status
property 2 times? 也许我在线程处理方面做错了什么,但是为什么仅在成功设置Status
属性2次后才引发异常?
I had an event handler, listening to the StatusChanged
event, in 1 if clause, I forgot to use the UI thread to update the UI 我有一个事件处理程序,在1 if子句中监听StatusChanged
事件,我忘记了使用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
};
Update : I missed the (in my defense, small) comment in your code that gave away that you're using WPF/Silverlight and not Windows Forms. 更新 :我错过了代码中的(为了辩护,在小的情况下)注释,但该注释表明您使用的是WPF / Silverlight,而不是Windows窗体。
Still, looks like you were able to take the basic gist of what I said and apply it to your own scenario properly (using Dispatcher.Invoke
rather than Control.Invoke
)—well done ;) 不过,看起来您已经能够理解我所说的基本内容并将其正确地应用于您自己的场景(使用Dispatcher.Invoke
而不是Control.Invoke
)—做得很好;)
I'm guessing an event handler attached to your StatusChanged
event updates a StatusLabel
control on your UI? 我猜测附加到StatusChanged
事件的事件处理程序会更新UI上的StatusLabel
控件吗? If that's the case, then you need to Invoke
that call from the UI thread; 如果是这种情况,那么您需要从UI线程Invoke
该调用; eg: 例如:
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();
}
}
The reason you might see two successes followed by a failure is a bit beyond me; 您可能会看到两次成功之后又一次失败的原因超出了我一些; but I know that the StatusLabel
control in particular can be a bit evasive when it comes to threading issues. 但是我知道,特别是在涉及线程问题时, StatusLabel
控件可能会有点回避。 I have seen code where it is updated directly from background threads (typically due to developer obliviousness) without any exception; 我已经看到了从后台线程直接进行更新的代码(通常是由于开发人员的遗忘),没有任何异常; it looks to me like you just got lucky twice and unlucky once. 在我看来,您幸运两次,而不幸一次。
Does Status
touch the UI? Status
是否触及用户界面? Because it seems like it. 因为看起来像。
I can only guess but I imagine Status
changes something on UI which needs to be done through Dispatcher.Invoke()
. 我只能猜测,但是我想Status
会在UI上发生一些变化,这需要通过Dispatcher.Invoke()
。
if Status is a global variable you will get this exception becuase multiple threads are accessing and updating it at the same time. 如果Status是全局变量,则由于多个线程正在同时访问和更新它,因此将获得此异常。 i suggest to use a lock around it 我建议在它周围使用锁
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.