调用线程无法访问此对象,因为另一个线程拥有它

时间:2010-11-22 13:39:32

标签: c#

好的,我当前的代码正在进行中,可能我会尝试使用Async CTP做同样的事情。但我仍然想了解发生了什么。

我有一个类似下面的功能

// 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 @pastebin 的完整代码。第76行Send()

我想知道为什么我会得到例外?也许我对线程做错了,但为什么只有在我成功设置Status属性2次后才会引发异常?

更新:原因......

我有一个事件处理程序,在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
};

3 个答案:

答案 0 :(得分:3)

更新:我错过了您的代码中的(在我的辩护中,小)评论,该评论表明您使用的是WPF / Silverlight,而不是Windows Forms。

尽管如此,看起来你能够理解我所说的基本要点并将其应用到你自己的场景中(使用Dispatcher.Invoke而不是Control.Invoke) - 做得好;)


我猜测附加到StatusChanged事件的事件处理程序会更新您的UI上的StatusLabel控件?如果是这种情况,则需要从UI线程调用Invoke; 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();
    }
}

你可能会看到两次失败后失败的原因有点超出我的意思;但我知道,当涉及到线程问题时,StatusLabel控件尤其可能有点回避。我已经看到代码直接从后台线程更新(通常由于开发人员的遗忘),没有任何异常;在我看来,你只是幸运了两次而且运气不好。

答案 1 :(得分:0)

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

我只能猜测,但我认为Status会在UI上发生一些需要通过Dispatcher.Invoke()进行更改的内容。

答案 2 :(得分:-1)

如果Status是一个全局变量,你会得到这个例外,因为多个线程同时访问和更新它。我建议用它锁一下