【问题标题】:Background process to update the GUI [closed]更新 GUI 的后台进程 [关闭]
【发布时间】:2017-11-02 03:57:25
【问题描述】:

我正在创建一个应用程序来从数据库中读取表并将它们转储到文件中。用户要求转储一个文件,然后作为第二个任务,然后是第三个等等。当任务完成或失败时,我希望在 GUI 上显示。我很难在我的任务和 GUI 之间进行通信。这是我的 gui 代码:

namespace ClientCsvDumper
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
async void go_Click(object sender, RoutedEventArgs e)
        {
            String database_name;
            String schema_name;
            String output_file_name;

            database_name = this.database_name.SelectedItem.ToString();

            output_file_name = this.output_file_name.Text;

            SqlConnection conn = new SqlConnection("Data Source="+this.server_name.Text+";Initial Catalog="+"MASTER"+";Integrated Security=True");
            if (this.query_button.IsChecked.Value) {
                String query_text;
                query_text = this.query_textbox.Text;
                thread_number++;
                await Task.Run(() => {
                    UpdateWindows("task " + thread_number.ToString() + " started");
                    AsyncDumpQueryToFile(conn, database_name, query_text, output_file_name);
                });


            }
            else {
                schema_name = this.schema_name.SelectedItem.ToString();
                String table_name;
                table_name = this.table_name.SelectedItem.ToString();
                thread_number++;
                await Task.Run(() => {UpdateWindows("task " + thread_number.ToString() + " started");
                    AsyncDumpTableToFile(conn, database_name, schema_name, table_name, output_file_name);
                });

             }

        }

async Task AsyncDumpTableToFile( SqlConnection connection, string database_name, string schema_name, string tableName, string destinationFile) {
           // gui.UpdateWindows("Work Started");
            TableDumper ts = new TableDumper();
            ts.DumpTableToFile(connection, database_name, schema_name, tableName, destinationFile);

          //  gui.UpdateWindows("Done");
        }
        async Task AsyncDumpQueryToFile( SqlConnection connection, string database_name, string query, string destinationFile)
        {
            //gui.UpdateWindows("Work Started");
            TableDumper ts = new TableDumper();
            ts.DumpQueryToFile( connection,  database_name,  query,  destinationFile);

           // gui.UpdateWindows("Done");
        }

        void UpdateWindows(String text) {

            Dispatcher.Invoke(() => { status.Text += text; });
        }

首先,我尝试(使用来自网络的代码)将 gui 0bject 传递给函数 AsyncDumpTableToFile(这样我就可以在 gui 上修改东西,但是说主线程使用并拥有它时崩溃了。

如何在主 GUI 上打印有关 runnin 任务的信息(已启动、运行、失败(异常消息)、成功)?

还有什么好书让我了解更多这类东西?

一切顺利

文森特

【问题讨论】:

  • 查看 BackgroundWorker 类。它拥有监控工作进度和完成所需的一切:msdn.microsoft.com/en-us/library/…
  • @Kevin:我不同意使用BackgroundWorker 的建议。这是一个足够体面的解决方案,我承认那里有很多关于如何使用它的信息,因为它已经存在了很长时间。但是现代 C# 代码将使用Task.Run(),如上面的代码所示。此时的建议应该有助于推动 OP 前进,而不是后退。
  • 致 OP:您正在使用 WPF,这意味着,在一般情况下,如果您使用带有 INotifyPropertyChanged 的视图模型对象并将数据绑定到 UI,跨线程更新将是自动处理。对于不起作用的场景,您可以使用Progress&lt;T&gt; 报告进度,当然也可以通过await 从任务方法返回对象。不幸的是,您的问题不包括能够可靠地重现您的问题的良好 minimal reproducible example,因此无法给您任何具体的建议或好的答案(尽管您可能会得到很多不好的答案)。
  • 也许您可以使用here 的解决方案,它使用 IProgress 报告状态
  • "...如果有任何用处的话" -- 不,那没用。作为在 Stack Overflow 上寻求帮助的人,您的职责之一是准备一个合适的、良好的 minimal reproducible example,它可以可靠地重现您的问题,并将其全部包含在您的问题中。阅读该链接页面,以及How to Ask,以及页面底部链接的文章,以更好地了解这意味着什么以及为什么它如此重要。

标签: c# wpf user-interface async-await


【解决方案1】:

我同意 Peter 的观点,您的理想解决方案将使用 MVVM。但是,您也可以使用基于 IProgress&lt;T&gt; 的现代方法直接访问 UI 元素,例如:

async void go_Click(object sender, RoutedEventArgs e)
{
  IProgress<string> progress = new Progress<string>(text => status.Text += text);
  ...
  await Task.Run(() =>
  {
    progress.Report("task " + thread_number.ToString() + " started");
    AsyncDump*ToFile(..., progress);
  });
  ...
}

async Task AsyncDump*ToFile(..., IProgress<string> progress)
{
  progress.Report("Work Started");
  ...
  progress.Report("Done");
}

此模式的重要部分是Progress&lt;T&gt; 对象必须在 UI 线程上创建。然后它将为您处理线程编组。

【讨论】:

  • 非常感谢它运行良好。
猜你喜欢
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-10
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
相关资源
最近更新 更多