[英]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.