如何在单独的线程中启动长时间运行的进程

时间:2011-11-25 09:57:10

标签: c# sql multithreading

好的,我们最后一部分差不多完成了!一个错误去嗯。 这是在使用这个建议,并且正在抱怨我认为的代表。

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);
        }
    }
}

}

不确定应该在哪里进行更改,现在不应该在帐户方法中吗?

2 个答案:

答案 0 :(得分:2)

您的代码中存在许多问题:

  • 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();
    }
    

答案 1 :(得分:1)

修正了一些轻微的拼写错误,当时没有手头的编译器。 到您的上一个错误:只需将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/en-us/library/system.threading.tasks.task.aspx http://blogs.msdn.com/b/pfxteam/archive/2009/06/30/9809774.aspx