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

时间:2015-02-18 14:19:15

标签: c# multithreading winforms asynchronous .net-4.5

在我的应用程序中,我有两种方法从csv加载数据。这些方法是loadData()loadOtherData()。我想并行运行它们,所以我有两个线程来运行它们。

loadData()方法还填充一个datagridview,而loadOtherData()方法加载的数据存储在字典myDictionary中。

数据加载完成后(所以两个线程中运行的方法已经完成)我想调用另一个以updateGrids()为参数的方法myDictionary

要使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()时收到错误,因为它没有可以使用的数据。如何轻松更改代码以使其正常工作?

3 个答案:

答案 0 :(得分:2)

您可以直接停止使用ThreadStart对象并使用Tasks - 让它们从loadData和loadOtherData方法返回。

这里有两个选项:

如果您正在使用.NET 4.0,请使用Task.WaitAll

或(更优选)......

在.NET 4.5及更高版本中生成loadData和loadOtherData async(或使用.NET 4.0中的async BCL包)。当您调用方法时,您可以缓存它们返回的Task对象并等待对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);
} 

答案 1 :(得分:1)

您可以使用async/await等待两个任务而不会阻止UI

async private void loadData_Click_1(object sender, EventArgs e)
{
    await Task.WhenAll(Task.Run(() => loadData()), 
                       Task.Run(() => loadOtherData()));

    updateGrids(myDictionary); 
}

答案 2 :(得分:-1)

启动线程后,您需要等到它们完成。所以添加以下代码行:

t1.Join();
t2.Join();

Join将导致当前线程休眠,直到加入的线程完成。

根据评论,我假设这是WinForms。在这种情况下,Join将阻止UI线程。您可以创建第三个线程来加入其他两个线程,然后调用Invoke来调用您的更新方法。

由于您正在使用.Net 4.5。,您可以使用Async / Await;将async修饰符添加到click方法事件处理程序中,并直接使用Tasks而不是Threads await。其他答案涵盖了这一点,您也可以看到此blog其他详细信息。