线程结束时启动方法

时间:2013-08-29 14:41:27

标签: c# multithreading winforms

我对线程相对较新,所以我不确定我是否正确处理这个问题。

在我目前的应用程序中,我有一个多标签导航表单,其中一些具有导致其他表单的按钮,其中一些表格有表格,其中一些表格同时存在。在其中一个,我有一个按钮来添加一个条目,一个表格显示通过存储过程拉出的那一天的所有条目。

当我打开第二个表单作为对话框时,通过调用我创建的方法很容易刷新表...但是,它运行缓慢。相反,我开始将它称为另一个线程,它运行得非常快,但我似乎找不到在线程结束时调用该方法的方法。我已经搜索了一段时间,但我找不到可行的解决方案。

以下是代码:

public static void ThreadProcAddEntry()
    {
        Application.Run(new AddEntry());
    }

    private void btnAdd_Click(object sender, EventArgs e)
    {
        System.Threading.Thread t = new Thread(new ThreadStart(ThreadProcAddEntry));
        t.Name = "AddEntry";
        t.Start();           
    }

public void GetMyEntries(string username)
    {
        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DB2"].ConnectionString))
        {
            using (SqlCommand cmd = new SqlCommand("SP_GetUserEntries", conn))
            {
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@UserID", SqlDbType.VarChar).Value = username;
                conn.Open();
                cmd.ExecuteNonQuery();
                SqlDataReader reader = cmd.ExecuteReader();

                using (reader)
                {
                    DataTable table = new DataTable();
                    table.Load(reader);
                    dgvMyEntry.DataSource = table;
                    dgvMyEntry.AllowUserToAddRows = false;
                    dgvMyEntry.ReadOnly = true;
                    dgvMyEntry.AutoResizeColumns();
                    dgvMyEntry.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
                }
            }
        }

    }

你怎么建议我在线程结束时运行GetMyEntries方法,一旦我点击AddEntryForm上的Submit按钮(在提交给SQL之后运行一个dispose方法)就会发生?

5 个答案:

答案 0 :(得分:2)

您可以使用.NET框架提供的另一个包装器方法/接口。那是BackgroundWorker。有关更多信息,请查看msnd http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

var backgroundWorker = new BackgroundWorker();

// define the event handlers
backgroundWorker.DoWork += (sender, args) => {
    // do your lengthy stuff here -- this will happen in a separate thread
    ...
}
backgroundWorker.RunWorkerCompleted += (sender, args) => {
    if (args.Error != null)  // if an exception occurred during DoWork,
        MessageBox.Show(args.Error.ToString());  // do your error handling here

    // Do whatever else you want to do after the work completed.
    // This happens in the main UI thread.
    ...
}

backgroundWorker.RunWorkerAsync(); // starts the background worker

答案 1 :(得分:2)

我建议使用任务,如下:

await Task
    .Run(() => ThreadProcAddEntry())
    .ContinueWith(task => GetMyEntries(username));

这比使用原始线程或后台工作者更简洁,更易读。

GetMyEntries将在ThreadProcAddEntry完成后立即运行。

有关任务并行库(async / await)的更多信息:http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

答案 2 :(得分:1)

我会使用任务

var task = Task.Run(() => ThreadProcAddEntry());

task.GetAwaiter().OnCompleted(() => GetMyEntries(username));

答案 3 :(得分:0)

您是否可以在GetMyEntries()之后致电Application.Run(new AddEntry());

如果它不在范围内,那么我担心我们需要更多关于您的架构的细节。

答案 4 :(得分:0)

您可以使用.net提供的一个有用的线程包装类,而不是使用原始线程。具体来说,这听起来像BackgroundWorker的完美工作。您将创建一个新的BackgroundWorker,将要在线程中运行的代码添加到BackgroundWorker的DoWork事件,将GetMyEntries添加到BackgroundWorker的RunWorkerCompleted事件,然后调用RunWorkerAsync()。