1

我对线程比较陌生,所以我不确定我是否正确地处理这个问题。

在我当前的应用程序中,我有一个多选项卡式导航表单,其中一些具有通向其他表单的按钮,其中一些具有表格,而其中一些具有两者。在一个这样的地方,我有一个按钮来添加一个条目,还有一个表格,显示当天通过存储过程提取的所有条目。

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

这是代码:

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 方法)?

4

5 回答 5

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
于 2013-08-29T14:46:53.300 回答
2

我建议使用任务,如下所示:

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

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

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

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

于 2013-08-29T14:53:21.460 回答
1

我会使用一个任务

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

task.GetAwaiter().OnCompleted(() => GetMyEntries(username));
于 2013-08-29T14:53:52.523 回答
0

您可以简单地调用GetMyEntries()afterApplication.Run(new AddEntry());吗?

如果不在范围内,那么恐怕我们需要您的架构的更多细节。

于 2013-08-29T14:44:18.100 回答
0

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

于 2013-08-29T14:46:37.767 回答