首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将代码从BGW转换为异步并等待DataTabale/MySQLDataAdapter

将代码从BGW转换为异步并等待DataTabale/MySQLDataAdapter
EN

Stack Overflow用户
提问于 2014-12-11 21:14:06
回答 2查看 220关注 0票数 0

我怎样才能放弃BGW而使用异步/等待任务,我愿意在使用VS2013的时候学习这项技术。

我在网上查看了示例,但我仍然无法自己完成,因为我遇到的示例使用了.NET中的现有函数,这些函数已经返回了一个任务。我试图分离BGW DoWork中的代码并创建一个任务,但编译器一直询问我等待的问题,我无论如何也无法调用该任务,我注意到需要花费时间的代码行是:

代码语言:javascript
运行
复制
SQLDataAdapter = new MySqlDataAdapter(SQLcmd);
SQLDataAdapter.Fill(dt);

我需要的是:在按钮内部单击开始从数据库读取数据的任务,然后解除表单挂起(假设我没有使用BGW),然后读取结果并在datagridview中显示它们。

代码语言:javascript
运行
复制
// code starts here
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
using System.IO;

namespace MySQLProject
{
    public partial class Form1 : Form
    {


        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            backgroundWorker1.RunWorkerAsync();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            string stdNo = File.ReadAllText("stdNo.txt").Replace(Environment.NewLine, ",");


            const string cs = @"what ever";
            MySqlConnection conn = new MySqlConnection(cs);
            MySqlDataAdapter SQLDataAdapter = new MySqlDataAdapter(); ;
            DataSet ds = new DataSet();
            conn.Open();
            this.InvokeEx(x => x.textBox1.AppendText(string.Format("MySQL version : {0};", conn.ServerVersion)));

            DataTable dt = new DataTable("StudentNamesAndNumbers");
            dt.Columns.Add("Student Name", typeof(string));
            dt.Columns.Add("Student ID", typeof(string));
            dt.Columns.Add("First", typeof(float));
            dt.Columns.Add("Second", typeof(float));
            dt.Columns.Add("Section", typeof(string));
            ds.Tables.Add(dt);

            try
            {

                MySqlCommand SQLcmd = new MySqlCommand();
                SQLcmd = conn.CreateCommand();
                SQLcmd.CommandText = String.Format(@"Select u.firstname as 'Student Name', u.username as 'Student ID'"
                                                    + ",( select  score from gradebook_result g , gradebook_evaluation e "
                                                    + "where g.user_id = u.user_id "
                                                    + "and name = 'First' "
                                                    + "and g.evaluation_id = e.id "
                                                    + "and e.course_code = c.course_code) as 'First' "
                                                    + ",( select  score from gradebook_result g , gradebook_evaluation e "
                                                    + "where g.user_id = u.user_id "
                                                    + "and name = 'Second' "
                                                    + "and g.evaluation_id = e.id "
                                                    + "and e.course_code = c.course_code) as 'Second' "
                                                    + ", c.course_code as 'Section'"
                                                    + "from user u, course_rel_user c "
                                                    + "where "
                                                    + "u.username in ({0}) "
                                                    + "and u.username REGEXP '[0-9]+' "
                                                    + "and c.course_code like 'IT102CPLUS%' "
                                                    + "and  u.user_id = c.user_id ;", stdNo);

                this.InvokeEx(x => x.textBox1.AppendText(SQLcmd.CommandText));

                SQLDataAdapter = new MySqlDataAdapter(SQLcmd);
                SQLDataAdapter.Fill(dt);
                dt.DefaultView.Sort = "Section ASC, Student Name ASC";
                this.InvokeEx(x => x.dataGridView1.Columns.Clear());
                this.InvokeEx(x => x.dataGridView1.DataSource = ds.Tables["StudentNamesAndNumbers"]);
                this.InvokeEx(x => x.dataGridView1.AutoResizeColumns());
                this.InvokeEx(x => x.label1.Text = dt.Rows.Count.ToString() + " Students");

                // =======================================================

                var lines = new List<string>();

                string[] columnNames = dt.Columns.Cast<DataColumn>().
                                                  Select(column => column.ColumnName).
                                                  ToArray();

                var header = string.Join(",", columnNames);
                lines.Add(header);

                var valueLines = dt.AsEnumerable().Select(row => string.Join(",", row.ItemArray));            
                lines.AddRange(valueLines);

                File.WriteAllLines("Export.csv", lines, Encoding.UTF8);

            }
            catch (MySqlException ex)
            {
                this.InvokeEx(x => x.textBox1.AppendText(string.Format("Error: {0}\n\n", ex.ToString())));
            }
            finally
            {
                if (conn != null)
                {
                    conn.Close();
                }
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            button1.Enabled = true;
        }
    }
}
EN

回答 2

Stack Overflow用户

发布于 2014-12-11 22:00:58

我有一个series on my blog,它显示了BackgroundWorkerTask.Run的比较。

通常,对于I/O受限的操作,不应该使用这两种方法中的任何一种。但是,有一些较旧的API尚未升级以公开TAP方法。我认为“数据适配器”和“数据表”API被认为太旧而无法升级,因此没有可以使用的"FillAsync“。

因此,假设您想保留“数据表”方法,您可以直接使用Task.Run作为BackgroundWorker的替代。请注意,IProgress<T>是一种更现代的方式,可以执行任何类型的跨线程调用来进行进度更新:

代码语言:javascript
运行
复制
private async void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false;
    var progress = new Progress<string>(update => textBox1.AppendText(update));
    var ds = await Task.Run(() => BackgroundWork(progress));
    dataGridView1.Columns.Clear();
    dataGridView1.DataSource = ds.Tables["StudentNamesAndNumbers"];
    dataGridView1.AutoResizeColumns();
    label1.Text = dataGridView1.Rows.Count.ToString() + " Students";
    button1.Enabled = true;
}

private DataSet BackgroundWork(IProgress<string> progress)
{
    string stdNo = File.ReadAllText("stdNo.txt").Replace(Environment.NewLine, ",");

    const string cs = @"what ever";
    MySqlConnection conn = new MySqlConnection(cs);
    MySqlDataAdapter SQLDataAdapter = new MySqlDataAdapter(); ;
    DataSet ds = new DataSet();
    conn.Open();
    if (progress != null)
        progress.Report(string.Format("MySQL version : {0};", conn.ServerVersion));

    DataTable dt = new DataTable("StudentNamesAndNumbers");
    dt.Columns.Add("Student Name", typeof(string));
    dt.Columns.Add("Student ID", typeof(string));
    dt.Columns.Add("First", typeof(float));
    dt.Columns.Add("Second", typeof(float));
    dt.Columns.Add("Section", typeof(string));
    ds.Tables.Add(dt);

    try
    {
        MySqlCommand SQLcmd = new MySqlCommand();
        SQLcmd = conn.CreateCommand();
        SQLcmd.CommandText = String.Format(@"Select u.firstname as 'Student Name', u.username as 'Student ID'"
                                                + ",( select  score from gradebook_result g , gradebook_evaluation e "
                                                + "where g.user_id = u.user_id "
                                                + "and name = 'First' "
                                                + "and g.evaluation_id = e.id "
                                                + "and e.course_code = c.course_code) as 'First' "
                                                + ",( select  score from gradebook_result g , gradebook_evaluation e "
                                                + "where g.user_id = u.user_id "
                                                + "and name = 'Second' "
                                                + "and g.evaluation_id = e.id "
                                                + "and e.course_code = c.course_code) as 'Second' "
                                                + ", c.course_code as 'Section'"
                                                + "from user u, course_rel_user c "
                                                + "where "
                                                + "u.username in ({0}) "
                                                + "and u.username REGEXP '[0-9]+' "
                                                + "and c.course_code like 'IT102CPLUS%' "
                                                + "and  u.user_id = c.user_id ;", stdNo);

        if (progress != null)
            progress.Report(SQLcmd.CommandText);

        SQLDataAdapter = new MySqlDataAdapter(SQLcmd);
        SQLDataAdapter.Fill(dt);
        dt.DefaultView.Sort = "Section ASC, Student Name ASC";
        var lines = new List<string>();

        string[] columnNames = dt.Columns.Cast<DataColumn>().
                                              Select(column => column.ColumnName).
                                              ToArray();

        var header = string.Join(",", columnNames);
        lines.Add(header);

        var valueLines = dt.AsEnumerable().Select(row => string.Join(",", row.ItemArray));            
        lines.AddRange(valueLines);

        File.WriteAllLines("Export.csv", lines, Encoding.UTF8);
        return ds;
    }
    catch (MySqlException ex)
    {
        if (progress != null)
            progress.Report(string.Format("Error: {0}\n\n", ex.ToString()));
    }
    finally
    {
        if (conn != null)
        {
            conn.Close();
        }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2014-12-11 21:25:50

您应该将该方法标记为async,并在可能的情况下等待异步方法。如果没有异步方法,并且您希望在另一个线程上运行同步方法,请等待Task.Run

代码语言:javascript
运行
复制
    private async void button1_Click(object sender, EventArgs e)
    {
        button1.Enabled = false;
        try
        {
            //Use an async method when there is one available
            string stdNo;
            using (var reader = File.OpenText("Words.txt"))
            {
                stdNo = await reader.ReadToEndAsync();
            }
            stdNo = stdNo.Replace(Environment.NewLine, ",");

            const string cs = @"what ever";
            MySqlConnection conn = new MySqlConnection(cs);
            MySqlDataAdapter SQLDataAdapter = new MySqlDataAdapter(); ;
            DataSet ds = new DataSet();

            //Use Task.Run to call a long running code on another thread
            //If available you should use await conn.OpenAsync();
            await Task.Run(() => conn.Open());
            //You don't need invoke, after an await you are back to the synchronization context
            textBox1.AppendText(string.Format("MySQL version : {0};", conn.ServerVersion));

            DataTable dt = new DataTable("StudentNamesAndNumbers");
            dt.Columns.Add("Student Name", typeof(string));
            dt.Columns.Add("Student ID", typeof(string));
            dt.Columns.Add("First", typeof(float));
            dt.Columns.Add("Second", typeof(float));
            dt.Columns.Add("Section", typeof(string));
            ds.Tables.Add(dt);
            //...
        }
        finally
        {
            button1.Enabled = true;
        }


    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27423756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档