2009-05-14 14 views
10

Dostaję taki błąd:Co to jest rodzic, który można zamrozić? Co oznacza ten błąd?

nie można użyć DependencyObject który należy do innego wątku niż jego rodzic freezable

Co to w ogóle znaczy? Czy to po angielsku? Czy rodzic jest zamrożony, czy jest to po prostu zamrożone? Jakikolwiek sposób, aby rodzic nie podlegał zamrożeniu, jeśli spowoduje, że błąd zniknie?

Co się dzieje:

Mam dwa OpenGL WinForms kontroli w aplikacji WPF, a do tej pory, wszystko to pracuje płynnie (myślę). Teraz dodałem aktualizację, więc gdy jedna formuła WinForm zaktualizuje obraz, druga powinna również. To faktycznie działało, a teraz dostaję tego błędu. Przechodzenie przez kod powoduje awarię w losowych miejscach, co prowadzi mnie do przekonania, że ​​jest to błąd zbierania śmieci (tj. Niektóre aktualizacje w innym wątku tworzą coś, co zbiera śmieci, a kolekcja dzieje się w losowym czasie).

Wyjątek został przechwycony metodą głównej metody i jest to wyjątek InvalidOperationException.

Chwytam tutaj słomki. Gdzie zaczynam?

EDIT: Wygląda na to wezwanie, które jest przyczyną problemu jest to jedno:

 if (imagePanel.InvokeRequired) 
     { 
      imagePanel.Invoke(new System.Windows.Forms.MethodInvoker(delegate{ 
       imagePanel.ClearImages(); 
      })); 
     } 
     else 
     { 
      imagePanel.ClearImages(); 
     } 

ja wciąż śledzenia go w dół; jeśli ta seria wierszy zostanie skomentowana, awaria nadal się zdarza, a status wątku ma wątek "właśnie zakończony" (stąd założenie wyrzucania śmieci).

+1

jeden z nielicznych przypadków, gdzie diagramów zdanie byłoby pomocne .. . –

+1

Niezwykle złe sformułowanie tytułu. Nikt nie może znaleźć tego pytania, szukając odpowiednich słów kluczowych, ponieważ żadna nie jest w tytule. To nie jest forum pomocy technicznej, właściwie sformułuj pytania ... – Timwi

+1

Hej, @Timwi, przeczytaj odpowiedź. Uświadom sobie, że zostawiłem tu tylko to pytanie, ponieważ znalazłem odpowiedź, ale było to bardzo frustrujące. Jeśli chcesz edytować tytuł, zdobądź więcej powtórzeń i zrób to sam, jak uważasz, że tak powinno być. – mmr

Odpowiedz

12

OK, wymyśliłem to. Zwykle po prostu usunę to pytanie, ale znalezienie informacji o tym rozwiązaniu było bardzo trudne.

Problemem było połączenia, który wyglądał tak:

ImageBrush theBrush = new ImageBrush(new Bitmap(new Uri(...))); 

if (labelStatus.Dispatcher.Thread == System.Threading.Thread.CurrentThread) { 
    button.background = theBrush; 
} 
else { 
    labelStatus.Dispatcher.BeginInvoke((System.Threading.ThreadStart)(delegate { 
    button.background = theBrush; 
    })); 
} 

Ale! jeśli to zrobisz, wtedy program rozsyłający działa, a następnie próbuje usunąć pędzel, ale sam pędzel jest również usuwany w innym miejscu.

Więc lekcja take-home jest, jeśli zadeklarować ImageBrush, a następnie usunąć go w tym samym wątku, tak jak poniżej:

void MyFunc(){ 
    ImageBrush theBrush = new ImageBrush(new Bitmap(new Uri(...))); 
    button.background = theBrush; 
} 

if (labelStatus.Dispatcher.Thread == System.Threading.Thread.CurrentThread) { 
    MyFunc(); 
} 
else { 
    labelStatus.Dispatcher.BeginInvoke((System.Threading.ThreadStart)(delegate { 
     MyFunc(); 
    })); 
}