C# 调用线程无法访问此对象,因为其他线程拥有它

C# 调用线程无法访问此对象,因为其他线程拥有它,c#,C#,好的,我当前的代码正在进行中,我可能会尝试用异步CTP做同样的事情。但我还是想知道发生了什么 我有一个如下的函数 // In MainWindow.xaml.cs Task.Factory.StartNew(() => helper.Send()); // In class HttpHelper public void Send() { // ... try { Status = Statuses.Uploading; // wr

好的,我当前的代码正在进行中,我可能会尝试用异步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的完整代码<代码>发送()第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。。。这个行动很聪明,足以解决这个问题。这让我的生活更轻松;)