2010-11-22 2 views
4

Хорошо, мой текущий код работает, и, вероятно, я попытаюсь сделать то же самое с 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. Send() on line 76

Интересно, почему я получаю исключение? Может быть, я сделал что-то не так с потоковой обработкой, но почему исключение возникает только после того, как я успешно установил свойство Status 2 раза?

UPDATE: Причина ...

Я имел обработчик события, прислушиваясь к StatusChanged события, в 1, если условие, я забыл использовать поток пользовательского интерфейса для обновления пользовательского интерфейса

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

потому что иногда вы получаете поток пользовательского интерфейса, а иногда нет. –

ответ

3

Обновление: Я пропустил (в моей защите, небольшой) комментарий в коде, который дал вам то, что вы используете WPF/Silverlight, а не Windows Forms.

Тем не менее, похоже, что Вы были в состоянии взять на себя основную суть того, что я сказал, и применить его к вашему собственному сценарию правильно (с использованием Dispatcher.Invoke вместо Control.Invoke) -Молодец;)


Я угадав, что обработчик событий, прикрепленный к вашему StatusChanged событиям, обновляет элемент управления StatusLabel на вашем пользовательском интерфейсе? Если это так, то вам нужно 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

+0

@Aliostad: Хороший звонок; В этом случае я вижу проблему. Я обновлю (снова) ... –

+0

@Aliostad: Er ... OP был достаточно умным, чтобы понять это. Это облегчает мою жизнь;) –

-1

если Status является глобальной переменной, вы получите это исключение, потому что несколько потоков одновременно обращаются к нему и обновляют его. я предлагаю использовать замок вокруг него

0

Status сенсорный интерфейс? Потому что это похоже.

Я могу только догадываться, но я полагаю, что Status что-то меняет в пользовательском интерфейсе, который нужно сделать через Dispatcher.Invoke().

Смежные вопросы

 Смежные вопросы