仅在其他线程上的作业终止后才调用方法?
Call a method only after jobs on other threads have terminated?
在我的应用程序中,我有两种从 csv 加载数据的方法。这些方法是 loadData()
和 loadOtherData()
。我想 运行 它们并行,所以我有两个线程 运行 它们。
loadData()
方法也填充一个datagridview,而loadOtherData()
方法加载的数据存储在字典myDictionary
中。
数据加载完成后(所以两个线程中的方法运行ning已经完成)我想调用另一个以myDictionary
为参数的方法updateGrids()
。
为了 updateGrids()
到 运行 正确,loadData()
和 loadOtherData()
都必须 运行 成功导致否则该方法没有数据从事于。
如何仅在其他方法在其他线程中终止时才调用方法 updateGrids()
?
结构如下:
private void loadData_Click_1(object sender, EventArgs e)
{
ThreadStart thread1Start = new ThreadStart(loadData); // load data and fill the first datagridview
ThreadStart thread2Start = new ThreadStart(loadOtherData); // load data and fill myDictionary
Thread t1 = new Thread(thread1Start);
Thread t2 = new Thread(thread2Start);
t1.Start();
t2.Start();
updateGrids(myDictionary); // call this method to update remaining datagridviews
}
private void updateGrids(Dictionary<string, double> myDictionary)
{
// update the remaining datagridviews by using
// information in the first datagridview and in myDictionary
}
但是如果我 运行 这个,我会在 updateGrids()
时收到错误,因为它没有要处理的数据。我怎样才能轻松更改代码以使其正常工作?
您可以停止直接使用 ThreadStart 对象并改用 Tasks - 让它们 return 从您的 loadData 和 loadOtherData 方法中编辑。
这里有两个选项:
如果您使用的是 .NET 4.0,请使用 Task.WaitAll
或(更可取)....
在 .NET 4.5 及更高版本中使 loadData 和 loadOtherData 异步(或在 .NET 4.0 中使用异步 BCL 包)。当您调用这些方法时,您可以缓存 return 的任务对象并等待对 Task.WhenAll
的调用
public async Task LoadData(){
}
public async Task LoadOtherData() {
}
private async void loadData_Click_1(object sender, EventArgs e)
{
var loadDataTask = LoadData();
var loadOtherDataTask = LoadOtherData();
await Task.WhenAll(loadDataTask, loadOtherDataTask);
updateGrids(myDictionary);
}
启动线程后,您想等到它们完成。所以添加这些代码行:
t1.Join();
t2.Join();
Join 将导致当前线程休眠,直到被加入的线程完成。
根据评论,我假设这是 WinForms。在这种情况下 Join
将阻塞 UI 线程。您可以创建第三个线程来加入其他两个线程,然后调用 Invoke 来调用您的更新方法。
由于您使用的是 .Net 4.5,因此您可以使用 Async / Await;将 async
修饰符添加到您的点击方法事件处理程序中,并直接使用任务而不是线程和 await
它们。其他答案涵盖了这一点,您也可以查看此 blog 了解其他详细信息。
您可以使用 async/await 等待两个任务而不会阻塞 UI
async private void loadData_Click_1(object sender, EventArgs e)
{
await Task.WhenAll(Task.Run(() => loadData()),
Task.Run(() => loadOtherData()));
updateGrids(myDictionary);
}
在我的应用程序中,我有两种从 csv 加载数据的方法。这些方法是 loadData()
和 loadOtherData()
。我想 运行 它们并行,所以我有两个线程 运行 它们。
loadData()
方法也填充一个datagridview,而loadOtherData()
方法加载的数据存储在字典myDictionary
中。
数据加载完成后(所以两个线程中的方法运行ning已经完成)我想调用另一个以myDictionary
为参数的方法updateGrids()
。
为了 updateGrids()
到 运行 正确,loadData()
和 loadOtherData()
都必须 运行 成功导致否则该方法没有数据从事于。
如何仅在其他方法在其他线程中终止时才调用方法 updateGrids()
?
结构如下:
private void loadData_Click_1(object sender, EventArgs e)
{
ThreadStart thread1Start = new ThreadStart(loadData); // load data and fill the first datagridview
ThreadStart thread2Start = new ThreadStart(loadOtherData); // load data and fill myDictionary
Thread t1 = new Thread(thread1Start);
Thread t2 = new Thread(thread2Start);
t1.Start();
t2.Start();
updateGrids(myDictionary); // call this method to update remaining datagridviews
}
private void updateGrids(Dictionary<string, double> myDictionary)
{
// update the remaining datagridviews by using
// information in the first datagridview and in myDictionary
}
但是如果我 运行 这个,我会在 updateGrids()
时收到错误,因为它没有要处理的数据。我怎样才能轻松更改代码以使其正常工作?
您可以停止直接使用 ThreadStart 对象并改用 Tasks - 让它们 return 从您的 loadData 和 loadOtherData 方法中编辑。
这里有两个选项:
如果您使用的是 .NET 4.0,请使用 Task.WaitAll
或(更可取)....
在 .NET 4.5 及更高版本中使 loadData 和 loadOtherData 异步(或在 .NET 4.0 中使用异步 BCL 包)。当您调用这些方法时,您可以缓存 return 的任务对象并等待对 Task.WhenAll
的调用public async Task LoadData(){
}
public async Task LoadOtherData() {
}
private async void loadData_Click_1(object sender, EventArgs e)
{
var loadDataTask = LoadData();
var loadOtherDataTask = LoadOtherData();
await Task.WhenAll(loadDataTask, loadOtherDataTask);
updateGrids(myDictionary);
}
启动线程后,您想等到它们完成。所以添加这些代码行:
t1.Join();
t2.Join();
Join 将导致当前线程休眠,直到被加入的线程完成。
根据评论,我假设这是 WinForms。在这种情况下 Join
将阻塞 UI 线程。您可以创建第三个线程来加入其他两个线程,然后调用 Invoke 来调用您的更新方法。
由于您使用的是 .Net 4.5,因此您可以使用 Async / Await;将 async
修饰符添加到您的点击方法事件处理程序中,并直接使用任务而不是线程和 await
它们。其他答案涵盖了这一点,您也可以查看此 blog 了解其他详细信息。
您可以使用 async/await 等待两个任务而不会阻塞 UI
async private void loadData_Click_1(object sender, EventArgs e)
{
await Task.WhenAll(Task.Run(() => loadData()),
Task.Run(() => loadOtherData()));
updateGrids(myDictionary);
}