我对线程相对较新,所以我不确定我是否正确处理这个问题。
在我目前的应用程序中,我有一个多标签导航表单,其中一些具有导致其他表单的按钮,其中一些表格有表格,其中一些表格同时存在。在其中一个,我有一个按钮来添加一个条目,一个表格显示通过存储过程拉出的那一天的所有条目。
当我打开第二个表单作为对话框时,通过调用我创建的方法很容易刷新表...但是,它运行缓慢。相反,我开始将它称为另一个线程,它运行得非常快,但我似乎找不到在线程结束时调用该方法的方法。我已经搜索了一段时间,但我找不到可行的解决方案。
以下是代码:
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方法)就会发生?
答案 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()。