在生命结束时关闭ProgressBar后台线程

时间:2014-11-17 21:51:02

标签: c# wpf multithreading progress-bar

在我的程序中,我使用一个单独的线程来读取外部文件并将数据传送到我的程序。我正在尝试在该线程运行时在UI线程上运行ProgressBar,以便向用户提供反馈。截至目前,我有一个ProgressBar打开,但没有关闭,因为我不知道如何告诉它子线程已经结束。我已经在ProgressBars上阅读了本教程,并且应该注意我的线程没有使用BackgroundWorker。而不是这个,我只是使用System.Threading.Thread。如果这是一个问题,请告诉我。

打开包含OpenFile()的Window的ProgressBar方法,并启动将执行打开文件工作的线程:

public void OpenFile()
{
    //Open Progress Bar Window
    LoadingWindow = new LoadingScreen(App.MainWindowViewModel.LoadScreen); 
    LoadingWindow.Show();
    App.MainWindowViewModel.LoadScreen.IsIndeterminate = true;

    FILE_INPUT = true; //bool that Signifies that the background thread is running

    //Create Thread -- run routines in thread
    var openFileThread = new Thread(() => openDefault(txtFile)); //Passes the file
    openFileThread.Start(); //Start File open thread
}

//This thread reads in the file and transfers the data to the program
private void openDefault(StreamReader txtFile)
{
    //Gathers info from file and changes program accordingly

    FILE_INPUT = false; //background thread is no longer running
}

截至目前,我没有ProgressBar的增量方法,因为我想确保在处理类似的技术细节之前我能够正常工作。无论如何,我的问题是......在我的程序中如何以及在何处知道后台线程已经完成并且LoadingWindowProgressBar)可以关闭?

更多代码可帮助您了解我的计划流程:

主窗口代码背后:

private void OpenFile_Click(object sender, RoutedEventArgs e)
{
    OpenFile(); //calls to the method that launches the new thread and the window with the Progress Bar

    //Wait until background Thread is complete
    while (ViewModel.FILE_INPUT == true) { }

    //After thread has stopped running, close the window (DOES NOT WORK)
    ViewModel.LoadingWindow.Close(); // -- Close Prog Bar
}

最终解决方案:

//In OpenFile() method
LoadingWindow = new LoadingScreen(App.MainWindowViewModel.LoadScreen); //Open Progress Bar Window
LoadingWindow.Show();
App.MainWindowViewModel.LoadScreen.IsIndeterminate = true;

FILE_INPUT = true; //A file is being inputted*

Dispatcher UIDispatcher = Dispatcher.CurrentDispatcher;

Task.Factory.StartNew(() =>
{
     openDefault(txtFile); //Passes the file
     //After thread has stopped running, close the Loading Window
     UIDispatcher.Invoke((Action)(() => LoadingWindow.Close())); //Close progress bar
});

1 个答案:

答案 0 :(得分:1)

如果没有完整的代码示例,很难提供完整的答案。根据您实际执行文件I / O和管理ProgressBar的方式,您可能还需要进行其他更改以改进代码。但为了解决眼前的问题,我建议您利用async / await模式:

public async Task OpenFile()
{
    //Open Progress Bar Window
    LoadingWindow = new LoadingScreen(App.MainWindowViewModel.LoadScreen); 
    LoadingWindow.Show();
    App.MainWindowViewModel.LoadScreen.IsIndeterminate = true;

    FILE_INPUT = true; //bool that Signifies that the background thread is running

    //Create Thread -- run routines in thread
    await Task.Run(() => openDefault(txtFile)); //Passes the file
}

private async void OpenFile_Click(object sender, RoutedEventArgs e)
{
    await OpenFile(); //calls to the method that launches the new thread and the window with the Progress Bar

    //After thread has stopped running, close the window
    ViewModel.LoadingWindow.Close(); // -- Close Prog Bar
}

这样可以避免在操作工作时导致UI冻结,同时允许以简单直接的方式编写代码。

通过上述更改,您可以完全摆脱FILE_INPUT变量(不清楚您可能正在使用它的其他内容,但它可能不是其他内容。)

请注意,OpenFile()方法已更改为返回Task。这是没有实际返回值的async方法的标准。对OpenFile_Click()方法进行相同的更改 ,但作为事件处理程序,通常需要返回void。两种语法都是合法的,但前者在可能的情况下是首选,因此可以访问Task对象(用于异常处理,完成等)。

编辑,对于那些没有.NET 4.5并且无法安装必要组件以支持async / await(这只是编译时更改)的人,这里是一个可以在.NET 4.0中运行的示例:

public void OpenFile()
{
    //Open Progress Bar Window
    LoadingWindow = new LoadingScreen(App.MainWindowViewModel.LoadScreen); 
    LoadingWindow.Show();
    App.MainWindowViewModel.LoadScreen.IsIndeterminate = true;

    FILE_INPUT = true; //bool that Signifies that the background thread is running

    //Create Thread -- run routines in thread
    Task.Factory.StartNew(() =>
    {
        openDefault(txtFile); //Passes the file
        //After thread has stopped running, close the window
        Dispatcher.Invoke((Action)(() => ViewModel.LoadingWindow.Close())); // -- Close Prog Bar
    });
}

private void OpenFile_Click(object sender, RoutedEventArgs e)
{
    //calls to the method that launches the new thread and the window with the Progress Bar
    OpenFile();
}

(这实际上在语义上与async / await实现略有不同,因为我只是将窗口关闭操作放在该任务中,而不是为第一个任务创建延续。但它应该有相同的净结果。)