C# 调用线程无法访问此对象,因为其他线程拥有它
好的,我当前的代码正在进行中,我可能会尝试用异步CTP做同样的事情。但我还是想知道发生了什么 我有一个如下的函数C# 调用线程无法访问此对象,因为其他线程拥有它,c#,C#,好的,我当前的代码正在进行中,我可能会尝试用异步CTP做同样的事情。但我还是想知道发生了什么 我有一个如下的函数 // In MainWindow.xaml.cs Task.Factory.StartNew(() => helper.Send()); // In class HttpHelper public void Send() { // ... try { Status = Statuses.Uploading; // wr
// 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)
{
// ...
}
}
HttpHelper的完整代码<代码>发送()第76行
我想知道为什么会有例外?也许我在线程方面做了一些错误,但是为什么只有在我成功地设置了状态
属性2次之后才会引发异常
更新:原因。。。
我有一个事件处理程序,监听StatusChanged
事件,在1if子句中,我忘记了使用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
};
如果Status是一个全局变量,则会出现此异常,因为多个线程同时访问和更新它。我建议在其周围使用锁状态是否触摸UI?因为看起来是这样
我只能猜测,但我可以想象,
状态
改变了UI上的某些事情,这些事情需要通过Dispatcher.Invoke()
更新:我错过了代码中的(为我辩护,很小的)注释,它泄露了您使用的是WPF/Silverlight而不是Windows窗体
尽管如此,看起来您还是能够理解我所说的基本要点,并将其正确地应用到您自己的场景中(使用Dispatcher.Invoke
而不是Control.Invoke
)-做得好;)
我猜一个附加到
StatusChanged
事件的事件处理程序会更新UI上的StatusLabel
控件吗?如果是这种情况,那么您需要从UI线程调用该调用;e、 g:
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();
}
}
void HttpHelper\u状态已更改(对象发送方,事件参数e)
{
var httpHelper=(httpHelper)发送方;
UpdateStatus(httpHelper.Status);
}
void UpdateStatus(HttpHelper.status状态)
{
如果(需要调用)
{
调用(新操作(更新状态),状态);
}
其他的
{
//您的代码可能不是这样的;
//这只是一个例子。
statusLabel.Text=status.ToString();
}
}
你可能会看到两次成功之后又是一次失败,这一点我有点难以理解;但是我知道,当涉及线程问题时,StatusLabel
控件可能会有点含糊不清。我看到的代码是直接从后台线程更新的(通常是由于开发人员的疏忽),没有任何例外;在我看来,你只是幸运了两次,不幸了一次。因为有时候你得到了UI线程,有时候你没有……虚拟-1。不它是Dispatcher.Invoke()。这是WPF/SilverLight,不是WPF@Aliostad:很好的呼叫;在这种情况下,我想我看到了问题所在。我会(再次)更新…@Aliostad:Er。。。这个行动很聪明,足以解决这个问题。这让我的生活更轻松;)