WPF 在单独的 UI 线程上加载动画? (C#)

2024-03-03

好的,我有一个加载动画,在填充大型数据表时运行,让用户知道程序尚未冻结。我的动画工作正常,但在数据表更新时它也会冻结。是否有某种方法可以拥有多个 UI 线程,以便在 DataTable 加载信息时动画能够继续运行?

编辑:当前代码如下。

private void CreateFileTable()
{
    file_data = new DataSet();
    data_table = new DataTable();
    file_data.Tables.Add(data_table);

    DataColumn tempCol = new DataColumn("File Name", typeof(string));
    data_table.Columns.Add(tempCol);

    tempCol = new DataColumn("Ext", typeof(string));
    data_table.Columns.Add(tempCol);

    tempCol = new DataColumn("Size", typeof(string));
    data_table.Columns.Add(tempCol);

    tempCol = new DataColumn("Created", typeof(Label));
    data_table.Columns.Add(tempCol);

    tempCol = new DataColumn("Modified", typeof(Label));
    data_table.Columns.Add(tempCol);

    tempCol = new DataColumn("Accessed", typeof(Label));
    data_table.Columns.Add(tempCol);

    tempCol = new DataColumn("Location", typeof(string));
    data_table.Columns.Add(tempCol);

    File_List.ItemsSource = file_data.Tables[0].DefaultView;
}

private void PopulateDirectories(string[] directories)
{
    for (int i = 0; i < directories.Length; i++)
    {
        DirectoryInfo tempDirInfo = new DirectoryInfo(directories[i]);

        bool isSystem = ((tempDirInfo.Attributes & FileAttributes.System) == FileAttributes.System);

        if (!isSystem)
        {
            DataRow tempRow = data_table.NewRow();
            tempRow["File Name"] = tempDirInfo.Name;
            tempRow["Ext"] = "";
            tempRow["Size"] = "";

            tempLabel = new Label();
            tempLabel.Padding = new Thickness(2, 0, 2, 0);
            tempLabel.Content = tempDirInfo.CreationTime.ToLongDateString() + ", " + tempDirInfo.CreationTime.ToLongTimeString();

            tempRow["Created"] = tempLabel;

            tempLabel = new Label();
            tempLabel.Padding = new Thickness(2, 0, 2, 0);
            tempLabel.Content = tempDirInfo.LastWriteTime.ToLongDateString() + ", " + tempDirInfo.LastWriteTime.ToLongTimeString();

            tempRow["Modified"] = tempLabel;

            tempLabel = new Label();
            tempLabel.Padding = new Thickness(2, 0, 2, 0);
            tempLabel.Content = tempDirInfo.LastAccessTime.ToLongDateString() + ", " + tempDirInfo.LastAccessTime.ToLongTimeString();

            tempRow["Accessed"] = tempLabel;
            tempRow["Location"] = tempDirInfo.FullName;

            data_table.Rows.Add(tempRow);
        }
    }
}

private void PopulateFiles(string[] files)
{
    for (int i = 0; i < files.Length; i++)
    {
        FileInfo tempFileInfo = new FileInfo(files[i]);

        bool isSystem = ((File.GetAttributes(files[i]) & FileAttributes.System) == FileAttributes.System);

        if (!isSystem)
        {
            DataRow tempRow = data_table.NewRow();
            tempRow["File Name"] = tempFileInfo.Name;
            tempRow["Ext"] = tempFileInfo.Extension;

            int fileSize = (int)tempFileInfo.Length;

            if (fileSize > 1048576)
            {
                tempRow["Size"] = "" + fileSize / 1048576 + " MB";
            }
            else if (fileSize > 1024)
            {
                tempRow["Size"] = "" + fileSize / 1024 + " KB";
            }
            else
            {
                tempRow["Size"] = "" + fileSize + " B";
            }

            tempLabel = new Label();
            tempLabel.Padding = new Thickness(2, 0, 2, 0);
            tempLabel.Content = tempFileInfo.CreationTime.ToLongDateString() + ", " + tempFileInfo.CreationTime.ToLongTimeString();

            tempRow["Created"] = tempLabel;

            tempLabel = new Label();
            tempLabel.Padding = new Thickness(2, 0, 2, 0);
            tempLabel.Content = tempFileInfo.LastWriteTime.ToLongDateString() + ", " + tempFileInfo.LastWriteTime.ToLongTimeString();

            tempRow["Modified"] = tempLabel;

            tempLabel = new Label();
            tempLabel.Padding = new Thickness(2, 0, 2, 0);
            tempLabel.Content = tempFileInfo.LastAccessTime.ToLongDateString() + ", " + tempFileInfo.LastAccessTime.ToLongTimeString();

            tempRow["Accessed"] = tempLabel;
            tempRow["Location"] = tempFileInfo.DirectoryName;

            data_table.Rows.Add(tempRow);
        }
    }
}

private string GetSelectedPath(TreeViewItem selectedNode)
{
    return selectedNode.Tag as string;
}

private void PopulateFileList()
{
    PopulateDirectories(Directory.GetDirectories(GetSelectedPath((TreeViewItem)Dir_Tree.SelectedItem)));
    PopulateFiles(Directory.GetFiles(GetSelectedPath((TreeViewItem)Dir_Tree.SelectedItem)));
}

private void UpdateFileList()
{
    LoadingWheel.Visibility = System.Windows.Visibility.Visible;

    CreateFileTable();
    PopulateFileList();
    TxtFoundCount.Text = "Files/Folders Found: " + File_List.Items.Count;

    LoadingWheel.Visibility = System.Windows.Visibility.Hidden;
}

我尝试过使用 BackgroundWorker 并调用其中的 UpdateFileList() 方法,但我没有任何运气。

编辑:下面是我的BackgroundWorker 代码。

private BackgroundWorker bgWorker1;

private void InitializeBackgroundWorker()
{
    bgWorker1 = new BackgroundWorker();
    bgWorker1.DoWork += new DoWorkEventHandler(bgWorker1_DoWork);
    bgWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker1_RunWorkerCompleted);
}

private void bgWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    if (Dispatcher.CheckAccess())
    {
        PopulateFileList();
    }
    else
    {
        Dispatcher.Invoke(new Action(() => PopulateFileList()));
    }
}

private void bgWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    TxtFoundCount.Text = "Files/Folders Found: " + File_List.Items.Count;
    LoadingWheel.Visibility = System.Windows.Visibility.Hidden;
}

private void UpdateFileList()
{
    LoadingWheel.Visibility = System.Windows.Visibility.Visible;
    CreateFileTable();
    bgWorker1.RunWorkerAsync();
}

我在 TreeView 上有一个 SelectionChanged 事件,它调用 InitializeBackgroundWorker() 和 UpdateFileList()。列表仍然加载,并且我没有收到任何错误,但加载动画永远不可见。

任何帮助将不胜感激。

Thanks.


只有一个 UI 线程。您需要做的是在不同的线程上加载DataTable 中的数据。

如果您想显示 DataTable 加载的进度(直接显示,或者通过 ProgressBar 或其他一些机制),后台工作者 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx这是一种相当简单的方法。

更新:非常简单的后台工作示例
这是一个相当简单的例子。它将 100 个随机数添加到集合中,在每个随机数之间暂停线程一小段时间以模拟长时间的加载过程。您可以简单地将其剪切并粘贴到您自己的测试项目中以查看其工作原理。

需要注意的是,繁重的工作(需要一段时间的工作)是在 DoWork 中完成的,而所有 UI 更新都是在 ProgressChanged 和 RunWorkerCompleted 中完成的。事实上,在 DoWork 处理程序中创建了一个单独的列表(数字),因为全局 mNumbers 集合位于 UI 线程上,并且无法在 DoWork 处理程序中进行交互。

XAML

<Button x:Name="btnGenerateNumbers"
        Grid.Row="1"
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        Content="Generate Numbers" />

C# 代码隐藏

BackgroundWorker bgWorker = new BackgroundWorker();
ObservableCollection<int> mNumbers = new ObservableCollection<int>();

public Window1()
{
    InitializeComponent();
    bgWorker.DoWork += 
        new DoWorkEventHandler(bgWorker_DoWork);
    bgWorker.ProgressChanged += 
        new ProgressChangedEventHandler(bgWorker_ProgressChanged);
    bgWorker.RunWorkerCompleted += 
        new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
    bgWorker.WorkerReportsProgress = true;

    btnGenerateNumbers.Click += (s, e) => UpdateNumbers();

    this.DataContext = this;
}

void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    progress.Visibility = Visibility.Collapsed;
    lstItems.Opacity = 1d;
    btnGenerateNumbers.IsEnabled = true;
}

void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    List<int> numbers = (List<int>)e.UserState;
    foreach (int number in numbers)
    {
         mNumbers.Add(number);
    }

    progress.Value = e.ProgressPercentage;
}

void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    Random rnd = new Random();
    List<int> numbers = new List<int>(10);

    for (int i = 1; i <= 100; i++)
    {
        // Add a random number
        numbers.Add(rnd.Next());            

        // Sleep from 1/8 of a second to 1 second
        Thread.Sleep(rnd.Next(125, 1000));

        // Every 10 iterations, report progress
        if ((i % 10) == 0)
        {
            bgWorker.ReportProgress(i, numbers.ToList<int>());
            numbers.Clear();
        }
    }
}

public ObservableCollection<int> NumberItems
{
    get { return mNumbers; }
}

private void UpdateNumbers()
{
    btnGenerateNumbers.IsEnabled = false;
    mNumbers.Clear();
    progress.Value = 0;
    progress.Visibility = Visibility.Visible;
    lstItems.Opacity = 0.5;

    bgWorker.RunWorkerAsync();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF 在单独的 UI 线程上加载动画? (C#) 的相关文章

  • C++ 标准是否允许未初始化的 bool 导致程序崩溃?

    我知道一个 未定义的行为 C 几乎可以让编译器做任何它想做的事情 然而 我遇到了一次令我惊讶的崩溃 因为我认为代码足够安全 在这种情况下 真正的问题仅发生在使用特定编译器的特定平台上 并且仅在启用优化的情况下发生 我尝试了几种方法来重现问题
  • 氧图。如何将轴旁边的值格式从 1000 更改为 1k

    我正在尝试更改轴旁边的值的格式 例如从 1000 更改为 1k 或 1000000 更改为 1M 这在 LinearAxis 中可能吗 这是我的代码 m Axes Add new LinearAxis Position AxisPositi
  • TCP客户端;网络流;异步读取; C#

    请原谅我对任务和异步缺乏了解 使用 TcpClient 类 我正在创建与可用服务器的连接 void async RunClientAsync TcpClient client new TcpClient try await client C
  • C++ 天花板函数的奇怪结果

    我一直在尝试天花板功能并得到一些奇怪的结果 如果我对十进制数乘以百执行 ceil 运算 我会得到一定的结果 但是 如果我直接对该乘法的结果执行 ceil 我会得到完全不同的输出 另一个问题是 这些不同的结果仅发生在某些数字上 任何帮助 将不
  • 如何在 C# 中启动文件

    编辑 我觉得自己像个白痴 我有一种感觉 像下面的答案会起作用 但没有看到任何与下面的答案类似的谷歌结果 所以当我看到这段复杂的代码时 我想它一定是这样的 我搜索并找到了这个Windows 列出并启动与扩展关联的应用程序 https stac
  • 如何在C中将2个4位无符号数组合成1个8位数

    我有 2 个 4 位数字 X0X1X2X3 和 Y0Y1Y2Y3 我想将它们组合起来 这样我就可以创建一个像这样的 8 位数字 X0X1X2X3 Y0Y1Y2Y3 gt X0Y0X1Y1X2Y2X3Y3 我知道如何连接它们以创建X0X1X1
  • 如何使用 C# 调用 REST API?

    这是我到目前为止的代码 public class Class1 private const string URL https sub domain com objects json api key 123 private const str
  • “gi.repository.Gtk”对象没有属性“gdk”

    我正在尝试使用 GTK 创建多线程 需要 Gtk gdk 但我收到有关没有 gdk 属性的错误 我正在使用带有 Raspbian 的 Raspberry Pi 这就是我导入 GTK 库的方式 try import pygtk pygtk r
  • 二元运算符重载、隐式类型转换

    class my bool private bool value public my bool bool value value value explicit operator bool return value friend my boo
  • 如何在C中递归地找到另一个字符串中的字符串位置?

    我们有一个任务来创建带有两个字符串参数的递归函数 原型应该是这样的 int instring char word char sentence 如果我们愿意调用函数 instring Word Another Word 它应该具有以下返回值
  • 模板“内联”函数的静态局部变量[重复]

    这个问题在这里已经有答案了 static的局部变量inline如果我的理解是正确的 C 中的函数保证像单个全局变量一样存在 如果inline函数是一个模板 编译器可以在哪里生成该函数的多个版本 下面这篇文章应该很好地回答你的问题 http
  • 将数字 n 拆分为 k 个不同数字的总和

    我有一个数字 n 我必须将它分成 k 个数字 使得所有 k 个数字都是不同的 k 个数字的总和等于 n 并且 k 最大 例如 如果 n 为 9 则答案应为 1 2 6 如果 n 为 15 则答案应为 1 2 3 4 5 这就是我尝试过的 v
  • 访问结构向量

    我有一个结构 struct OutputStore int myINT string mySTRING 如果我创建一个 OutputStore 类型的数组 如下所示 OutputStore OutputFileData new Output
  • 如何在 .NET 中自定义 JSON 枚举的反序列化?

    我有以下示例 C 代码 它是使用 svcutil exe 应用程序从 xsd 自动生成的 DataContract public enum Foo EnumMember Value bar Bar 1 EnumMember Value ba
  • 我的 Opencv 应用程序处理速度非常慢

    我正在构建一个 OpenCV 应用程序 它从相机捕获视频 并在删除背景后将其覆盖在另一个视频上 我无法达到合理的速度 因为它以大约 1 fps 的速度播放输出 而我的背景去除以 3 fps 的速度工作 有没有办法以正常速度显示背景视频并以
  • C# 的 xml 序列化中是否有一个属性可以跳过空数组?

    C 的 xml 序列化中是否有一个属性可以跳过空数组 这将提高 xml 输出的可读性 好吧 你也许可以添加一个ShouldSerializeFoo method using System using System ComponentMode
  • Roslyn,通过 hostObject 传递值

    我正在尝试通过 hostObject 发送一个类 但显然它不想工作 using Roslyn Compilers using Roslyn Compilers CSharp using Roslyn Scripting using Rosl
  • 将 .NET 类库(主要定义 CRUD 操作)公开为服务

    公开现有内容的最佳 有效和最快的方法是什么 类 图书馆 主要定义 CRUD 操作 作为service 周转基金服务 or WCF数据服务 以便它可以与银光 or Ajax 在那儿tools 代码生成器 RAD 工具 哪些可以支持这个 预先感
  • 返回右值 - 这段代码有什么问题? [复制]

    这个问题在这里已经有答案了 我遇到了以下代码片段 std string test std string m Hello return std move m int main std string m test 我知道上面的代码是不正确且不安
  • 使用 Powershell 或 C# 获取 Azure“文件和文件夹”作业状态

    我一直在尝试找到一种方法来获取在 AzureRM 中运行的几个客户上运行的 文件和文件夹 备份作业的状态 可以在 AzureRm 门户中手动找到状态 恢复服务保管库 gt 作业 gt 备份作业 使用powershell不显示任何作业信息 G

随机推荐

  • 在android上使用ormlite删除?

    我有一个客户端 bean DatabaseField columnName client id generatedId true useGetSet true private Integer clientId DatabaseField c
  • 如何在网页视图中播放本地 swf 文件

    我正在尝试在 webview 中播放本地 swf 文件 保存在 asset 或 sdcard 中 但我没有运气 任何人都可以指导我正确的方法吗 我可以通过 url 播放 swf 文件 但是在 webview 中播放本地文件时遇到困难 swf
  • 如何使用 gson 库将字符串转换为 JsonObject

    请指教如何转换String to JsonObject using gson图书馆 我不成功的做法 String string abcde Gson gson new Gson JsonObject json new JsonObject
  • 如何忽略部分文本并在剩余部分进行搜索和替换? [复制]

    这个问题在这里已经有答案了 在文本文件中进行正则表达式查找和替换时 我想跳过并忽略文本的某些片段 也就是说 应该将文本的某些部分排除在搜索之外 而只对其余部分进行搜索和替换 标准是 1 任何介于START and END应从搜索和替换中排除
  • 通过 Enum 快速递增

    我喜欢 Swift 允许使用枚举方法 我正在尝试使用一种方法 但正在寻找一种更具可扩展性的方法来执行此操作 enum CopyState case binary hex both init self both mutating func n
  • 转换运算符:gcc 与 clang

    考虑以下代码 https godbolt org z s17aoczj6 https godbolt org z s17aoczj6 template
  • 使用 D3 创建 DIV 动态列表

    我一直在使用D3 http d3js org创建精美的动画图表 并且示例很棒 然而 我正在尝试做一些看似更基本的事情 但遇到了麻烦 将数据绑定到简单的 DIV 列表 我设置了enter 以不透明度 0 初始化元素 transition 让它
  • 使用尺寸类别时 UITableViewCell 子视图报告不正确的宽度

    由于某种原因 当在 xcode 6 中使用尺寸类时 我的单元格中的子视图宽度不正确 我有一个UIImageView使用自动布局调整大小 常量 顶部 左 右 底部为 10 当从以下位置调用以下内容时tableView tableView UI
  • jQuery 'mmenu' 打开时的回调事件

    使用 jQuery菜单插件 http mmenu frebsite nl 我需要在菜单打开后调用 JavaScript 函数 我看不到从API文档 http mmenu frebsite nl documentation api html如
  • 如何将字符转换为等效的 System.Windows.Input.Key Enum 值?

    我想写一个这样的函数 public System Windows Input Key ResolveKey char charToResolve Code goes here that resolves the charToResolve
  • Flask SQLAlchemy 不会关闭 MySQL 数据库连接

    我有一个 Flask 应用程序 使用 Flask SQLAlchemy 和 MySQL 数据库 其中数据库定义如下 db py from flask sqlalchemy import SQLAlchemy db SQLAlchemy ma
  • VBA宏快速删除行

    我有几个非常大的 Excel 数据文件 我需要遍历它们并删除 T 列中单元格值为 1 的所有行 现在我的代码如下所示 Sub test Dim cell As Range For Each cell In Worksheets Sheet1
  • 下载blob存储并返回Json对象

    我正在尝试下载一个 json我存储在容器中的 blobAzure Storage using Newtonsoft Json将其写入对象 我通过调用来做到这一点 CloudBlockBlob blob DownloadToStream st
  • PostgreSQL - 错误:查询没有结果数据的目标

    为什么我会收到以下错误 错误 查询没有结果数据的目标 这是我的功能 CREATE OR REPLACE FUNCTION public SumASCII value character varying RETURNS int LANGUAG
  • 由点聚类着色的等高线图 matlab

    我有两个向量 它们是成对的值 size X 1e4 x 1 size Y 1e4 x 1 是否可以绘制一个contour plot某种方式通过最高密度的点来制作轮廓 即最高聚类 红色 然后在其他地方渐变颜色 如果您需要更多说明 请询问 问候
  • 引用另一个 Snakemake 规则的输入或输出文件

    如何以编程方式引用另一个 Snakemake 规则的属性 我需要更换什么
  • 为什么惰性评估有用?

    我长期以来一直想知道为什么惰性评估有用 我还没有人以一种有意义的方式向我解释 大多数情况下 它最终都会归结为 相信我 注意 我的意思不是记忆 主要是因为它可以更有效 如果不使用值 则不需要计算它们 例如 我可以将三个值传递到一个函数中 但根
  • 如何消除数字范围中的重叠 (AWK)

    我正在尝试删除文件内的重叠部分 有一堆以 A 开头的记录 并且具有 起始值 和 结束值 还有一堆以 B 开头的记录 也有范围 并且显示与以 A 开头的记录可能重叠 这个想法是从 A 中删除重叠范围 以便只存在非重叠范围 B 中的某些记录具有
  • 为什么GCC的ifstream >> double分配这么多内存?

    我需要读取一系列数字以空格分隔的人类可读文件 https earth info nga mil GandG wgs84 gravitymod egm96 ww15mgh grd z并做了一些数学计算 但我在读取文件时遇到了一些真正奇怪的内存
  • WPF 在单独的 UI 线程上加载动画? (C#)

    好的 我有一个加载动画 在填充大型数据表时运行 让用户知道程序尚未冻结 我的动画工作正常 但在数据表更新时它也会冻结 是否有某种方法可以拥有多个 UI 线程 以便在 DataTable 加载信息时动画能够继续运行 编辑 当前代码如下 pri