![]() |
知识渊博的跑步鞋 · 如何使用PythonSDK执行滚动升级任务_ ...· 7 月前 · |
![]() |
博学的显示器 · C# WinForm中ListView ...· 10 月前 · |
![]() |
讲道义的松鼠 · flutter floating ...· 1 年前 · |
![]() |
忐忑的保温杯 · BottomNavigationView-- ...· 1 年前 · |
我怎样才能放弃BGW而使用异步/等待任务,我愿意在使用VS2013的时候学习这项技术。
我在网上查看了示例,但我仍然无法自己完成,因为我遇到的示例使用了.NET中的现有函数,这些函数已经返回了一个任务。我试图分离BGW DoWork中的代码并创建一个任务,但编译器一直询问我等待的问题,我无论如何也无法调用该任务,我注意到需要花费时间的代码行是:
SQLDataAdapter = new MySqlDataAdapter(SQLcmd);
SQLDataAdapter.Fill(dt);
我需要的是:在按钮内部单击开始从数据库读取数据的任务,然后解除表单挂起(假设我没有使用BGW),然后读取结果并在datagridview中显示它们。
// 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);
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;
}
发布于 2014-12-11 22:00:58
我有一个
series on my blog
,它显示了
BackgroundWorker
与
Task.Run
的比较。
通常,对于I/O受限的操作,不应该使用这两种方法中的任何一种。但是,有一些较旧的API尚未升级以公开TAP方法。我认为“数据适配器”和“数据表”API被认为太旧而无法升级,因此没有可以使用的"FillAsync“。
因此,假设您想保留“数据表”方法,您可以直接使用
Task.Run
作为
BackgroundWorker
的替代。请注意,
IProgress<T>
是一种更现代的方式,可以执行任何类型的跨线程调用来进行进度更新:
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);
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();
}
发布于 2014-12-11 21:25:50
您应该将该方法标记为
async
,并在可能的情况下等待异步方法。如果没有异步方法,并且您希望在另一个线程上运行同步方法,请等待
Task.Run
。
private async void button1_Click(object sender, EventArgs e)
button1.Enabled = false;
//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