[英]Running long-time background task in a separate background thread vs process
[英]How to start a long running process in a separate thread
好的,我们到最后一步几乎完成了! 一个错误。 这是在使用建议,并且在抱怨我认为的代表。
using System;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
pictureBox2.Visible = false;
}
private void button1_Click(object sender, EventArgs e)
{
Task t = new Task(() => GetsalesFigures(accCollection.Text));
t.Start();
}
private void SetPictureBoxVisibility(bool IsVisible)
{
if (pictureBox2.InvokeRequired)
{
pictureBox2.Invoke(new Action<bool>(SetPictureBoxVisibility), new Object[] { IsVisible });
}
else
{
pictureBox2.Visible = IsVisible;
}
}
private void SetCheckBoxValue(bool IsChecked)
{
if (checkBox1.InvokeRequired)
{
pictureBox2.Invoke(new Action<bool>(SetCheckBoxValue), new Object[] { IsChecked });
}
else
{
checkBox1.Checked = IsChecked;
}
}
private void AddItem(string value)
{
if (accCollection.InvokeRequired)
{
accCollection.Invoke(new Action<string>(AddItem), new Object[] { value });
}
else
{
accCollection.Items.Add(value);
}
}
private void Form1_Load(object sender, EventArgs e)
{
AutofillAccounts();
}
private void GetsalesFigures(string Acct)
{
try
{
string myConn = "Server=af" +
"Database=sdfta;" +
"uid=busdf4;" +
"pwd=drsdft;" +
"Connect Tisdf=120;";
string acct;// test using 1560
SqlConnection conn = new SqlConnection(myConn);
SqlCommand Pareto = new SqlCommand();
BindingSource bindme = new BindingSource();
SqlDataAdapter adapt1 = new SqlDataAdapter(Pareto);
DataSet dataSet1 = new DataSet();
DataTable table1 = new DataTable();
//CREATE THE THREAD
//acct = accCollection.Text;
acct = Acct;
string fromDate = this.dateTimePicker1.Value.ToString("MM/dd/yyyy");
string tooDate = this.dateTimePicker2.Value.ToString("MM/dd/yyyy");
Pareto.Connection = conn;
Pareto.CommandType = CommandType.StoredProcedure;
Pareto.CommandText = "dbo.GetSalesParetotemp";
Pareto.CommandTimeout = 120;
Pareto.Parameters.AddWithValue("@acct", acct);
Pareto.Parameters.AddWithValue("@from", fromDate);
Pareto.Parameters.AddWithValue("@too", tooDate);
//pictureBox2.Visible = true;
//checkBox1.Checked = true;
SetCheckBoxValue(true);
SetPictureBoxVisibility(true);
adapt1.Fill(dataSet1, "Pareto");
//checkBox1.Checked = false;
//pictureBox2.Visible = false;
SetCheckBoxValue(false);
SetPictureBoxVisibility(true);
this.dataGridView1.AutoGenerateColumns = true;
this.dataGridView1.DataSource = dataSet1;
this.dataGridView1.DataMember = "Pareto";
dataGridView1.AutoResizeColumns(
DataGridViewAutoSizeColumnsMode.AllCells);
SetPictureBoxVisibility(true);
acct = Acct;
}
catch (Exception execc)
{
MessageBox.Show("Whoops! Seems we couldnt connect to the server!"
+ " information:\n\n" + execc.Message + execc.StackTrace,
"Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
}
private void AutofillAccounts()
{
//get customers list and fill combo box on form load.
try
{
string myConn1 = "Server=sdf33;" +
"Database=sdft;" +
"uid=bdf4;" +
"pwd=ddft;" +
"Connect Timeout=6000;";
SqlConnection conn1 = new SqlConnection(myConn1);
conn1.Open();
SqlCommand accountFill = new SqlCommand("SELECT keycode FROM dbo.Customer", conn1);
SqlDataReader readacc = accountFill.ExecuteReader();
while (readacc.Read())
{
AddItem(readacc.GetString(0).ToString());
}
conn1.Close();
}
catch(Exception exc1)
{
MessageBox.Show("Whoops! Seems we couldnt connect to the server!"
+ " information:\n\n" + exc1.Message + exc1.StackTrace,
"Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
}
}
}
不确定应该在哪里进行更改,现在不应该使用帐户方法吗?
您的代码中有很多问题:
对Application.Run()
的调用是阻塞调用。 除非您关闭表格,否则它不会返回。 因此,线程将在应用程序即将退出时启动。
只需在调用Run()之前启动线程:
Thread aniSql = new Thread(new ThreadStart(getSalesFigures)); aniSql.Start(); Application.Run(new Form1());
提示:开始使用调试器并逐步执行代码。 您可能已经注意到,永远不会达到线程功能。
您在函数GetSalesFigures
创建Form1的第二个实例。 轮询复选框的状态时,必须使用现有实例。
您的线程将仅执行一次检查,然后返回。 您必须在GetSalesFigures
编写一些代码,以等待用户选中该复选框。 否则,将不会发生任何事情。 您可以使用ManualResetEvent
等待事件:
ManualResetEvent mre = new ManualResetEvent(false); void YourThreadFunc() { // Wait until someone signals mre mre.WaiteOne(); // start sql ... }
以您的形式:
private void button1_Click(object sender, EventArgs e) { // trigger the WaitHandle to signal the waiting thread mre.Set(); }
修复了一些小的拼写错误,当时没有编译器。 对于最后一个错误:只需将accCollection.Text作为参数提供给您的方法。 请参阅更新的button1_Click()和GetsalesFigures(String Acct)。 这就是我的Partial Class:Form的样子
public Form1()
{
InitializeComponent();
pictureBox2.Visible = false;
}
private void Form1_Load(object sender, EventArgs e)
{
AutofillAccounts();
}
private void button1_Click(object sender, EventArgs e)
{
checkBox1.Checked = true;
string acct = accCollection.Text;
Task t = new Task(() => GetsalesFigures(acct));
t.Start();
}
private void GetsalesFigures(String Acct)
{
// (...)
//pictureBox2.Visible = true; use SetPictureBoxVisibility
SetPictureBoxVisibility(true);
//checkBox1.Checked = true; use SetCheckBoxValue
SetCheckBoxValue(true);
// (...)
SetCheckBoxValue(false);
SetPictureBoxVisibility(false);
// (...)
acct = Acct;
// (...)
SetDataGrid(true, dataSet1, "Pareto", DataGridViewAutoSizeColumnsMode.AllCells);
}
private void AutofillAccounts()
{
// (...)
while (readacc.Read())
{
AddItem(readacc.GetString(0).ToString());
}
}
private void SetCheckBoxValue(bool IsChecked)
{
if (checkBox1.InvokeRequired)
{
pictureBox2.Invoke(new Action<bool>(SetCheckBoxValue), new Object[] { IsChecked });
}
else
{
checkBox1.Checked = IsChecked;
}
}
private void SetPictureBoxVisibility(bool IsVisible)
{
if (pictureBox2.InvokeRequired)
{
pictureBox2.Invoke(new Action<bool>(SetPictureBoxVisibility), new Object[] { IsVisible });
}
else
{
pictureBox2.Visible = IsVisible;
}
}
// Your latest comment
private void AddItem(string value)
{
if (accCollection.InvokeRequired)
{
accCollection.Invoke(new Action<string>(AddItem), new Object[] { value });
}
else
{
accCollection.Items.Add(value);
}
}
private void SetDataGrid(bool AutoGenerateColumns, Object DataSource, String DataMember, DataGridViewAutoSizeColumnsMode Mode)
{
if (this.dataGridView1.InvokeRequired)
{
this.dataGridView1.Invoke(new Action<bool, Object, String, DataGridViewAutoSizeColumnsMode>(SetDataGrid),
AutoGenerateColumns, DataSource, DataMember, Mode);
}
else
{
this.dataGridView1.AutoGenerateColumns = AutoGenerateColumns;
this.dataGridView1.DataSource = DataSource;
this.dataGridView1.DataMember = DataMember;
dataGridView1.AutoResizeColumns(Mode);
}
}
和Program.cs
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
总结您的问题:您必须封装要从另一个线程(而不是主线程)调用的所有与控件相关的更新,就像我对两个控件所做的一样。
您可能要检查多线程/任务的一些资源http://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task.aspx http://blogs.msdn.com/b/pfxteam/存档/2009/06/30/9809774.aspx
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.