У меня есть длинная операция, я бы хотел показать индикатор занятости Extended Toolkits. Я сделал предыдущий пост об этом, и он был исправлен Wpf Extended toolkit BusyIndicator not showing during operation. Однако во время этого вызова мне нужно взаимодействовать с элементом пользовательского интерфейса (canvas), и я получаю «вызывающий поток должен быть STA, потому что для этого требуется множество компонентов пользовательского интерфейса». Я понимаю (сейчас), что фоновой работник (см. Код):Показание индикатора занятости в потоке STA
private void CboItemId_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
BackgroundWorker _backgroundWorker = new BackgroundWorker();
_backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_backgroundWorker_RunWorkerCompleted);
ItemSearchBusyIndicator.IsBusy = true;
// Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
if (RdoItemSearch.IsChecked == false) return;
///backgroundWorker_DoWork(null, null);
if (CboItemId.SelectedValue == null) return;
if (CboItemId.SelectedValue.ToString() != string.Empty)
{
selectedItem = CboItemId.SelectedValue.ToString();
_backgroundWorker.RunWorkerAsync();
}
// Mouse.OverrideCursor = System.Windows.Input.Cursors.Arrow;
}
public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
LoadItemData(selectedItem);
}
использует MTA и не может быть установлен в STA. Так что я попытался назвать внутреннюю функцию, которая использует elelment UI в своем собственном потоке:
public void LoadItemData(string itemId)
{
Axapta ax = new Axapta();
files.Clear();
try
{
ax.Logon(Settings.Default.Server, null, Settings.Default.Test, null);
AxaptaContainer path = (AxaptaContainer)ax.CallStaticClassMethod(Settings.Default.ClassName, Settings.Default.ItemData, itemId);
for (int i = 1; i <= path.Count; i++)
{
AxaptaContainer somestring = (AxaptaContainer)path.get_Item(i);
for (int j = 1; j <= somestring.Count; j += 2)
{
string extension = Path.GetExtension(somestring.get_Item(j + 1).ToString().ToLower());
if (extension == ".jpg"
|| extension == ".jpeg"
|| extension == ".gif"
|| extension == ".png"
|| extension == ".bmp"
|| extension == ".pdf")
/* key=path - value=description */
files.Add(somestring.get_Item(j + 1).ToString(), somestring.get_Item(j).ToString());
}
}
// _canvas.Children.Clear();
Thread t = new Thread(new ThreadStart(LoadPictures));
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
ax.Logoff();
}
}
Heres где я взаимодействую с холста элемента:
private void LoadPictures()
{
foreach (DictionaryEntry filePath in files)
{
try
{
Picture p = new Picture();
ToolTip t = new ToolTip();
t.Content = filePath.Value;
p.ToolTip = t;
TextBlock tb = new TextBlock();
tb.Text = filePath.Value.ToString();
Canvas.SetTop(tb, y);
Canvas.SetLeft(tb, x);
p.ImagePath = filePath.Key.ToString();
p.OriginalImagePath = filePath.Key.ToString();
p.ImageName = filePath.Value.ToString();
_canvas.Children.Add(p); //<-------This is where i seem to error
}
catch (Exception ex)
{
MessageBox.Show("Error:" + ex.Message,"File Load Error",MessageBoxButton.OK,MessageBoxImage.Error);
}
}
}
, но я получаю «Вызывающий поток не может получить доступ к этот объект, потому что ему принадлежит другой поток » Я не знаю, как вызвать функцию long (LoadItemData()), показывая BusyIndicator без фонового рабочего. Любая помощь приветствуется
Почему бы вам не сделать его проще и использовать объект control.Dispatcher? –
см. Здесь http://stackoverflow.com/questions/7428260/wp7-invalid-cross-thread-access-scheduledtaskagent/7428442#7428442, он должен быть похож на wpf – thumbmunkeys
Вы должны вызвать LoadPictures() из обработчика события RunWorkerCompleted BGW , –