问题
Hi there is a follow up to another question here
Here is the summary
In a wpf application in c# I had a long process of updating a remote database. to do this I created a background worker. However I wanted to have a window open and a progressbar run during the database update routine. All my attempts to achieve this on my main window with a progressbar set to Indeterminate failed as the "swishing" effect on my progressbar did not start to run on my main window till after my background worker thread had finished
Any with help and this article here I managed to open a new window in a different thread and run the background worker and have the progressbar "swish" properly and the background work run to completion. HOWEVER, my new question is
How do I close my progressbar window (called progressDialog) once my background work is finished?
Please bear in mind that I am quite new to this and code examples would be greatly apprieciated and I THINK, but I am not certain I am going to want to close the progressbar window from the background worker RunWorkerCompleted area of code
here is my code
I set up the background worker as
public partial class MainWindow : Window
{
//Declare background workers
BackgroundWorker bwLoadCSV = new BackgroundWorker();
//Declare class variables
// some stuff
public MainWindow()
{
InitializeComponent();
//assign events to backgroundworkers
bwLoadCSV.WorkerReportsProgress = true;
bwLoadCSV.WorkerSupportsCancellation = true;
bwLoadCSV.DoWork += new DoWorkEventHandler(bwLoadCSV_DoWork);
bwLoadCSV.ProgressChanged += new ProgressChangedEventHandler(bwLoadCSV_ProgressChanged);
bwLoadCSV.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwLoadCSV_RunWorkerCompleted);
}
}
I run the event on a button click event as;
private void CSV_Load_Click(object sender, RoutedEventArgs e)
///Function to read csv into datagrid
///
{
//Turn Cursor to wait
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
Thread backgroundThread = new Thread(
new ThreadStart(() =>
{
ProgressDialog progressDialog = new ProgressDialog();
progressDialog.tbEvent.Text = "Loading CSV Data....";
progressDialog.progressBar1.IsIndeterminate = true;
progressDialog.ShowDialog();
}
));
backgroundThread.SetApartmentState(ApartmentState.STA);
backgroundThread.Start();
//Test connection to sql server
if (CHHoursDataProvider.IsDatabaseOnline() == false)
{
System.Windows.Forms.MessageBox.Show("Can not establish contact with sql server" + "\n" + "Contact IT", "Connection Error");
//Set UI picture
return;
}
//Set a control to update the user here
tbLoadDgStat.Visibility = Visibility.Visible;
//tbLoadDgStat.Text = "Getting data templete from Database...";
string FilePath = txFilePath.Text;
if (bwLoadCSV.IsBusy != true)
{
//load the context object with parameters for Background worker
bwCSVLoadContext Context = new bwCSVLoadContext();
Context.Site = cBChSite.Text;
Context.FilePath = txFilePath.Text;
Context.FileName = fileTest;
Context.Wageyear = cbWageYear.Text;
Context.Startdate = ((DateTime)dpStartDate.SelectedDate);
Context.Enddate = ((DateTime)dpEndDate.SelectedDate);
bwLoadCSV.RunWorkerAsync(Context);
}
}
My progressbar form progressDialog xaml and class are this;
<Window x:Class="Test_Read_CSV.ProgressDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Progress Dialog" Height="115" Width="306" Name="ProgressPopup">
<Grid>
<ProgressBar Height="31" HorizontalAlignment="Left" Margin="12,33,0,0" Name="progressBar1" VerticalAlignment="Top" Width="250" x:FieldModifier="public" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="7,4,0,0" Name="tbEvent" VerticalAlignment="Top" Width="254" IsReadOnly="True" IsEnabled="False" x:FieldModifier="public" />
</Grid>
class is
public partial class ProgressDialog : Window
{
public ProgressDialog()
{
WindowStartupLocation = WindowStartupLocation.CenterScreen;
InitializeComponent();
progressBar1.IsIndeterminate = true;
}
My background worker completed code is
private void bwLoadCSV_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
bwCSVLoadContext Context = e.Result as bwCSVLoadContext;
Thread.Sleep(5000);
if ((e.Cancelled == true))
{
this.tbLoadDgStat.Text = "Canceled!";
System.Threading.Thread.Sleep(1000);
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
tbLoadDgStat.Visibility = Visibility.Hidden;
}
else if (!(e.Error == null))
{
//this.tbProgress.Text = ("Error: " + e.Error.Message);
}
else
{
if (Context.LoadResult == true)
{
this.dgCSVData.DataContext = oTable.DefaultView;
btUpload.IsEnabled = true;
}
**//close the progressbar window some how here!!!**
//On the main window
this.tbLoadDgStat.Text = "Complete";
progressBar1.Value = 100;
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
tbLoadDgStat.Visibility = Visibility.Hidden;
}
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
}
回答1:
Do the Background in the progress page
If you need to pass (and return) an object then do so in the Progress ctor
private void click(object sender, RoutedEventArgs e)
{
Progress progressDialog = new Progress();
progressDialog.Show();
if (progressDialog != null) progressDialog = null;
}
namespace BackGroundWorkerShowDialog
{
/// <summary>
/// Interaction logic for Progress.xaml
/// </summary>
public partial class Progress : Window
{
BackgroundWorker bwLoadCSV = new BackgroundWorker();
public Progress()
{
InitializeComponent();
//assign events to backgroundworkers
bwLoadCSV.WorkerReportsProgress = true;
bwLoadCSV.WorkerSupportsCancellation = true;
bwLoadCSV.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
bwLoadCSV.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
bwLoadCSV.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
if (bwLoadCSV.IsBusy != true)
{
// Start the asynchronous operation.
bwLoadCSV.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; i <= 10; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);
worker.ReportProgress(i * 10);
}
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
//resultLabel.Text = "Canceled!";
}
else if (e.Error != null)
{
//resultLabel.Text = "Error: " + e.Error.Message;
}
else
{
//resultLabel.Text = "Done: " + e.Error.Message;
}
this.Close();
}
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
this.tbProgress.Text = e.ProgressPercentage.ToString();
}
}
}
来源:https://stackoverflow.com/questions/19362040/closing-a-wpf-window-created-on-a-different-thread-from-the-background-worker-wo