仅在其他线程上的作业终止后才调用方法?

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