表单上的 C# 线程

标签 c# winforms multithreading

Possible Duplicate:
How to update GUI from another thread in C#?

我目前有一个 C# 程序来运行查询并在 datagridview 中显示结果.

由于记录大小,查询需要一段时间(20-30 秒)才能运行。

我想我应该添加一个动画,这样用户至少知道软件正在运行并且没有停止工作。

当然,当调用过程时我无法运行任何东西,所以我研究了线程。

这是我的代码(请原谅我,我还没有真正添加注释):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Threading;

namespace RepSalesNetAnalysis
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            pictureBox2.Visible = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            GetsalesFigures();   
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            AutofillAccounts();
        }


        private void GetsalesFigures()
        {
            try
            {
                string myConn = "Server=herp;" +
                            "Database=shaftdata;" +
                            "uid=fake;" +
                            "pwd=faker;" +
                            "Connect Timeout=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();

                Thread aniSql = new Thread(new ThreadStart(animateIcon));//CREATE THE THREAD


                acct = accCollection.Text;

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

                aniSql.Start();                //START THE THREAD!
                adapt1.Fill(dataSet1, "Pareto");
                aniSql.Abort();                //KILL THE THREAD!
                //pictureBox2.Visible = false;

                this.dataGridView1.AutoGenerateColumns = true;
                this.dataGridView1.DataSource = dataSet1;
                this.dataGridView1.DataMember = "Pareto";

                dataGridView1.AutoResizeColumns(
                    DataGridViewAutoSizeColumnsMode.AllCells);

            }
            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=derp;" +
                                "Database=AutoPart;" +
                                "uid=fake;" +
                                "pwd=faker;" +
                                "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())
                {
                    this.accCollection.Items.Add(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);
            }
        }
        public void animateIcon()
        {
            // animate
            pictureBox2.Visible = true;  
        }
    }
}

如您所见,我想在过程调用之前运行动画,然后在调用之后结束动画。

我对线程的了解是全新的。我环顾四周,但现在有点困惑。

这是我的错误:

Thrown: "Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on." (System.InvalidOperationException) Exception Message = "Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.", Exception Type = "System.InvalidOperationException"

我需要一种非常简单的方法来在我的 sql 过程读取时执行动画。

类似于 picture.visible = true开始时为 false,结束时为 false。

最佳答案

如果您想执行此操作,则需要调用。

          private delegate void InvokeDelegate();

          public void DoSomething()
          {
               if (InvokeRequired)
               {
                    Invoke(new InvokeDelegate(DoSomething));
                    return;
               }
               // dosomething
          }

您还可以向委托(delegate)添加变量并使用它们:

      private delegate void InvokeDelegate(string text);
      public void DoSomething(string text)
      {
           if (InvokeRequired)
           {
                Invoke(new InvokeDelegate(DoSomething), text);
                return;
           }
           // dosomething with text
      }

希望这有帮助:)。

斯特凡

关于表单上的 C# 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8258839/

相关文章:

java - 同步两个线程未同步工作

c# - variable.ToString() 与 Convert.ToString(variable)

c# - 比较 2 个字符串时如何将一个值替换为另一个值?

c# - 截取按键删除

c# - 我的 Windows 窗体按钮设置为宽度 0,而它应该是全宽

c - 关于 C 中 POSIX 线程的问题

c# - Azure 应用服务 - 同步期间日期时间更改

c# - Nancy.DynamicDictionary 不包含 X 的定义

c# - 隔离 Winforms GUI 无响应原因的方法

c# - c# 定时器自然是多线程的吗?