Я знаю и использую метод xxx.Dispatcher.Invoke (), чтобы получить фоновый поток для манипулирования элементами GUI. Я думаю, что столкнулся с чем-то похожим, но немного другим, где я хочу, чтобы долго выполняемая фоновая задача создала дерево объектов, и когда это было сделано, передайте его в графический интерфейс для отображения.
Попытка сделать это приводит к InvalidOperationException, «из-за вызывающего потока не может получить доступ к этому объекту, потому что другой поток владеет им». Любопытно, что это не происходит с простым шрифтом.
Вот пример кода, который демонстрирует тривиальный случай, когда выбрасывается исключение. Есть идеи, как обойти это? Я почти уверен, что проблема в том, что фоновый поток владеет созданным на заводе объектом, и что поток графического интерфейса переднего плана не может стать владельцем, хотя он работает для более простых типов систем.
private void button1_Click(object sender, RoutedEventArgs e)
{
// These two objects are created on the GUI thread
String abc = "ABC";
Paragraph p = new Paragraph();
BackgroundWorker bgw = new BackgroundWorker();
// These two variables are place holders to give scoping access
String def = null;
Run r = null;
// Initialize the place holders with objects created on the background thread
bgw.DoWork += (s1,e2) =>
{
def = "DEF";
r = new Run("blah");
};
// When the background is done, use the factory objects with the GUI
bgw.RunWorkerCompleted += (s2,e2) =>
{
abc = abc + def; // WORKS: I suspect there's a new object
Console.WriteLine(abc); // Console emits 'ABCDEF'
List<String> l = new List<String>(); // How about stuffing it in a container?
l.Add(def); // WORKS: l has a reference to def
// BUT THIS FAILS.
p.Inlines.Add(r); // Calling thread cannot access this object
};
bgw.RunWorkerAsync();
}
Большая проблема заключается в том, что у меня есть большой документ, который я создаю на лету в фоновом режиме, и мне хотелось бы, чтобы графический интерфейс показывал, что было сгенерировано до сих пор, не дожидаясь завершения.
Как фоновый работник может выступать в качестве фабрики объектов и передавать контент в основной поток?
Спасибо!