gpt4 book ai didi

c# - 在STA线程上显示忙碌指示器

转载 作者:行者123 更新时间:2023-12-03 13:04:38 25 4
gpt4 key购买 nike

我要进行长时间的操作,希望显示“扩展工具包”的繁忙状态指示器。我之前对此发表过一篇文章,它是固定的Wpf Extended toolkit BusyIndicator not showing during operation。但是,在该调用期间,我必须与UI元素( Canvas )进行交互,并且得到一个“调用线程必须是STA,因为许多UI组件都需要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。因此,我尝试调用在其自己的线程中使用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();
}
}
这是我与canvas元素进行交互的地方:
      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);
}
}
}
但我收到“调用线程无法访问该对象,因为其他线程拥有它”
我不知道在没有背景工作人员的情况下显示BusyIndi​​cator时如何调用长时间运行的(LoadItemData())函数。任何帮助表示赞赏

最佳答案

有多种方法:

1)Async binding,不建议使用,但它在那里。您可以在属性getter中运行长时间运行的任务,完成后,框架将阻止UI阻塞-UI将得到更新。

2)使用BackgroundWorkerTask/Thread运行代码,但将其调用到UI线程中。在您的示例中:

Dispatcher.InvokeAsync(() => _canvas.Children.Add(p));

3)您可以完全阻止主窗口的UI线程,没有问题。但是要表明它正忙,可以在另一个线程中创建一个窗口,并在其中显示忙状态(运行动画等):
        var thread = new Thread(() =>
{
var window = new SomeWindow();
window.ShowDialog();
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();

关于c# - 在STA线程上显示忙碌指示器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30397022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com